From b74255e1f3c5d9344b68534a5549c354da7b031b Mon Sep 17 00:00:00 2001 From: Jack Turner Date: Fri, 26 Feb 2021 16:12:51 +0000 Subject: [PATCH] v2 --- LICENCE | 21 - README.md | 60 +- autodl/__init__.py | 1 + autodl/nas_201_api/__init__.py | 11 + autodl/nas_201_api/api_201.py | 274 +++++++ autodl/nas_201_api/api_301.py | 222 ++++++ autodl/nas_201_api/api_utils.py | 750 +++++++++++++++++++ autodl/procedures/__init__.py | 25 + autodl/procedures/basic_main.py | 75 ++ autodl/procedures/funcs_nasbench.py | 203 +++++ autodl/procedures/optimizers.py | 204 +++++ autodl/procedures/search_main.py | 126 ++++ autodl/procedures/search_main_v2.py | 87 +++ autodl/procedures/simple_KD_main.py | 94 +++ autodl/procedures/starts.py | 64 ++ autodl/utils/__init__.py | 5 + autodl/utils/affine_utils.py | 125 ++++ autodl/utils/evaluation_utils.py | 16 + autodl/utils/flop_benchmark.py | 181 +++++ autodl/utils/gpu_manager.py | 70 ++ autodl/utils/nas_utils.py | 57 ++ autodl/utils/weight_watcher.py | 319 ++++++++ config_utils/cifar-split.txt | 4 - datasets/__init__.py | 1 + datasets/data.py | 69 ++ datasets/get_dataset_with_transform.py | 28 + env.yml | 24 + environment.yml | 54 -- models/cell_infers/tiny_network.py | 2 +- nas_101_api/__init__.py | 1 + nas_101_api/base_ops.py | 65 ++ nas_101_api/graph_util.py | 167 +++++ nas_101_api/model.py | 252 +++++++ nas_101_api/model_spec.py | 152 ++++ nas_201_api/__init__.py | 15 + nas_201_api/api.py | 830 +++++++++++++++++++++ nas_201_api/api_201.py | 274 +++++++ nas_201_api/api_utils.py | 750 +++++++++++++++++++ nasspace.py | 360 +++++++++ plot_histograms.py | 144 ---- plot_scores.py | 285 +++++++ process_results.py | 87 --- pycls/core/__init__.py | 0 pycls/core/benchmark.py | 136 ++++ pycls/core/builders.py | 88 +++ pycls/core/checkpoint.py | 98 +++ pycls/core/config.py | 500 +++++++++++++ pycls/core/distributed.py | 157 ++++ pycls/core/io.py | 77 ++ pycls/core/logging.py | 138 ++++ pycls/core/meters.py | 435 +++++++++++ pycls/core/net.py | 129 ++++ pycls/core/optimizer.py | 95 +++ pycls/core/plotting.py | 132 ++++ pycls/core/timer.py | 39 + pycls/core/trainer.py | 419 +++++++++++ pycls/models/__init__.py | 0 pycls/models/anynet.py | 406 ++++++++++ pycls/models/common.py | 108 +++ pycls/models/effnet.py | 232 ++++++ pycls/models/nas/genotypes.py | 634 ++++++++++++++++ pycls/models/nas/nas.py | 299 ++++++++ pycls/models/nas/operations.py | 201 +++++ pycls/models/regnet.py | 89 +++ pycls/models/resnet.py | 280 +++++++ reproduce.sh | 13 - results/arch_score_acc.pd | Bin 2132531 -> 0 bytes results/histograms_cifar10val_batch256.png | Bin 31102 -> 0 bytes score_networks.py | 164 ++++ scorehook.sh | 32 + scores.py | 21 + search.py | 206 ++--- utils.py | 100 +++ visualiser.py | 81 -- 74 files changed, 11326 insertions(+), 537 deletions(-) delete mode 100644 LICENCE create mode 100644 autodl/__init__.py create mode 100644 autodl/nas_201_api/__init__.py create mode 100644 autodl/nas_201_api/api_201.py create mode 100644 autodl/nas_201_api/api_301.py create mode 100644 autodl/nas_201_api/api_utils.py create mode 100644 autodl/procedures/__init__.py create mode 100644 autodl/procedures/basic_main.py create mode 100644 autodl/procedures/funcs_nasbench.py create mode 100644 autodl/procedures/optimizers.py create mode 100644 autodl/procedures/search_main.py create mode 100644 autodl/procedures/search_main_v2.py create mode 100644 autodl/procedures/simple_KD_main.py create mode 100644 autodl/procedures/starts.py create mode 100644 autodl/utils/__init__.py create mode 100644 autodl/utils/affine_utils.py create mode 100644 autodl/utils/evaluation_utils.py create mode 100644 autodl/utils/flop_benchmark.py create mode 100644 autodl/utils/gpu_manager.py create mode 100644 autodl/utils/nas_utils.py create mode 100644 autodl/utils/weight_watcher.py delete mode 100644 config_utils/cifar-split.txt create mode 100644 datasets/data.py create mode 100644 env.yml delete mode 100644 environment.yml create mode 100644 nas_101_api/__init__.py create mode 100644 nas_101_api/base_ops.py create mode 100644 nas_101_api/graph_util.py create mode 100644 nas_101_api/model.py create mode 100644 nas_101_api/model_spec.py create mode 100644 nas_201_api/__init__.py create mode 100644 nas_201_api/api.py create mode 100644 nas_201_api/api_201.py create mode 100644 nas_201_api/api_utils.py create mode 100644 nasspace.py delete mode 100644 plot_histograms.py create mode 100644 plot_scores.py delete mode 100644 process_results.py create mode 100644 pycls/core/__init__.py create mode 100644 pycls/core/benchmark.py create mode 100644 pycls/core/builders.py create mode 100644 pycls/core/checkpoint.py create mode 100644 pycls/core/config.py create mode 100644 pycls/core/distributed.py create mode 100644 pycls/core/io.py create mode 100644 pycls/core/logging.py create mode 100644 pycls/core/meters.py create mode 100644 pycls/core/net.py create mode 100644 pycls/core/optimizer.py create mode 100644 pycls/core/plotting.py create mode 100644 pycls/core/timer.py create mode 100644 pycls/core/trainer.py create mode 100644 pycls/models/__init__.py create mode 100644 pycls/models/anynet.py create mode 100644 pycls/models/common.py create mode 100644 pycls/models/effnet.py create mode 100644 pycls/models/nas/genotypes.py create mode 100644 pycls/models/nas/nas.py create mode 100644 pycls/models/nas/operations.py create mode 100644 pycls/models/regnet.py create mode 100644 pycls/models/resnet.py delete mode 100755 reproduce.sh delete mode 100644 results/arch_score_acc.pd delete mode 100644 results/histograms_cifar10val_batch256.png create mode 100644 score_networks.py create mode 100644 scorehook.sh create mode 100644 scores.py create mode 100644 utils.py delete mode 100644 visualiser.py diff --git a/LICENCE b/LICENCE deleted file mode 100644 index 1c526fa..0000000 --- a/LICENCE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 BayesWatch - -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/README.md b/README.md index ff40fce..46e3540 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,31 @@ -# [Neural Architecture Search Without Training](https://arxiv.org/abs/2006.04647) +# Neural Architecture Search Without Training -This repository contains code for replicating our paper, [NAS Without Training](https://arxiv.org/abs/2006.04647). +> :warning: Note: this repository has been updated to reflect the second version of the paper to appear on arXiv 1 March. :warning -## Setup +## Usage -1. Download the [datasets](https://drive.google.com/drive/folders/1L0Lzq8rWpZLPfiQGd6QR8q5xLV88emU7). -2. Download [NAS-Bench-201](https://drive.google.com/file/d/16Y0UwGisiouVRxW-W5hEtbxmcHw_0hF_/view). -3. Install the requirements in a conda environment with `conda env create -f environment.yml`. +Create a conda environment using the env.yml file -We also refer the reader to instructions in the official [NAS-Bench-201 README](https://github.com/D-X-Y/NAS-Bench-201). - -## Reproducing our results - -To reproduce our results: - -``` -conda activate nas-wot -./reproduce.sh 3 # average accuracy over 3 runs -./reproduce.sh 500 # average accuracy over 500 runs (this will take longer) +```bash +conda env create -f env.yml ``` -Each command will finish by calling `process_results.py`, which will print a table. `./reproduce.sh 3` should print the following table: +Activate the environment and follow the instructions to install -| Method | Search time (s) | CIFAR-10 (val) | CIFAR-10 (test) | CIFAR-100 (val) | CIFAR-100 (test) | ImageNet16-120 (val) | ImageNet16-120 (test) | -|:-------------|------------------:|:-----------------|:------------------|:------------------|:-------------------|:-----------------------|:------------------------| -| Ours (N=10) | 1.75 | 89.50 +- 0.51 | 92.98 +- 0.82 | 69.80 +- 2.46 | 69.86 +- 2.21 | 42.35 +- 1.19 | 42.38 +- 1.37 | -| Ours (N=100) | 17.76 | 87.44 +- 1.45 | 92.27 +- 1.53 | 70.26 +- 1.09 | 69.86 +- 0.60 | 43.30 +- 1.62 | 43.51 +- 1.40 +Install nasbench (see https://github.com/google-research/nasbench) -`./reproduce 500` will produce the following table: +Download the NDS data from https://github.com/facebookresearch/nds and place the json files in naswot-codebase/nds_data/ +Download the NASbench101 data (see https://github.com/google-research/nasbench) +Download the NASbench201 data (see https://github.com/D-X-Y/NAS-Bench-201) -| Method | Search time (s) | CIFAR-10 (val) | CIFAR-10 (test) | CIFAR-100 (val) | CIFAR-100 (test) | ImageNet16-120 (val) | ImageNet16-120 (test) | -|:-------------|------------------:|:-----------------|:------------------|:------------------|:-------------------|:-----------------------|:------------------------| -| Ours (N=10) | 1.67 | 88.61 +- 1.58 | 91.58 +- 1.70 | 67.03 +- 3.01 | 67.15 +- 3.08 | 39.74 +- 4.17 | 39.76 +- 4.39 | -| Ours (N=100) | 17.12 | 88.43 +- 1.67 | 91.24 +- 1.70 | 67.04 +- 2.91 | 67.12 +- 2.98 | 40.68 +- 3.41 | 40.67 +- 3.55 | - - - -To try different sample sizes, simply change the `--n_samples` argument in the call to `search.py`, and update the list of sample sizes [this line](https://github.com/BayesWatch/nas-without-training/blob/master/process_results.py#L51) of `process_results.py`. - -Note that search times may vary from the reported result owing to hardware setup. - - -## Plotting histograms - -In order to plot the histograms in Figure 1 of the paper, run: +Reproduce all of the results by running +```bash +./scorehook.sh ``` -python plot_histograms.py -``` -to produce: - -![alt text](results/histograms_cifar10val_batch256.png) The code is licensed under the MIT licence. -## Acknowledgements - -This repository makes liberal use of code from the [AutoDL](https://github.com/D-X-Y/AutoDL-Projects) library. We also rely on [NAS-Bench-201](https://github.com/D-X-Y/NAS-Bench-201). - ## Citing us If you use or build on our work, please consider citing us: diff --git a/autodl/__init__.py b/autodl/__init__.py new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/autodl/__init__.py @@ -0,0 +1 @@ + diff --git a/autodl/nas_201_api/__init__.py b/autodl/nas_201_api/__init__.py new file mode 100644 index 0000000..5fd84d6 --- /dev/null +++ b/autodl/nas_201_api/__init__.py @@ -0,0 +1,11 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +##################################################### +from .api_utils import ArchResults, ResultsCount +from .api_201 import NASBench201API +from .api_301 import NASBench301API + +# NAS_BENCH_201_API_VERSION="v1.1" # [2020.02.25] +# NAS_BENCH_201_API_VERSION="v1.2" # [2020.03.09] +# NAS_BENCH_201_API_VERSION="v1.3" # [2020.03.16] +NAS_BENCH_201_API_VERSION="v2.0" # [2020.06.30] diff --git a/autodl/nas_201_api/api_201.py b/autodl/nas_201_api/api_201.py new file mode 100644 index 0000000..49d9a68 --- /dev/null +++ b/autodl/nas_201_api/api_201.py @@ -0,0 +1,274 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +############################################################################################ +# NAS-Bench-201: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 # +############################################################################################ +# The history of benchmark files: +# [2020.02.25] NAS-Bench-201-v1_0-e61699.pth : 6219 architectures are trained once, 1621 architectures are trained twice, 7785 architectures are trained three times. `LESS` only supports CIFAR10-VALID. +# [2020.03.16] NAS-Bench-201-v1_1-096897.pth : 2225 architectures are trained once, 5439 archiitectures are trained twice, 7961 architectures are trained three times on all training sets. For the hyper-parameters with the total epochs of 12, each model is trained on CIFAR-10, CIFAR-100, ImageNet16-120 once, and is trained on CIFAR-10-VALID twice. +# +# I'm still actively enhancing this benchmark. Please feel free to contact me if you have any question w.r.t. NAS-Bench-201. +# +import os, copy, random, torch, numpy as np +from pathlib import Path +from typing import List, Text, Union, Dict, Optional +from collections import OrderedDict, defaultdict + +from .api_utils import ArchResults +from .api_utils import NASBenchMetaAPI +from .api_utils import remap_dataset_set_names + + +ALL_BENCHMARK_FILES = ['NAS-Bench-201-v1_0-e61699.pth', 'NAS-Bench-201-v1_1-096897.pth'] +ALL_ARCHIVE_DIRS = ['NAS-Bench-201-v1_1-archive'] + + +def print_information(information, extra_info=None, show=False): + dataset_names = information.get_dataset_names() + strings = [information.arch_str, 'datasets : {:}, extra-info : {:}'.format(dataset_names, extra_info)] + def metric2str(loss, acc): + return 'loss = {:.3f}, top1 = {:.2f}%'.format(loss, acc) + + for ida, dataset in enumerate(dataset_names): + metric = information.get_compute_costs(dataset) + flop, param, latency = metric['flops'], metric['params'], metric['latency'] + str1 = '{:14s} FLOP={:6.2f} M, Params={:.3f} MB, latency={:} ms.'.format(dataset, flop, param, '{:.2f}'.format(latency*1000) if latency is not None and latency > 0 else None) + train_info = information.get_metrics(dataset, 'train') + if dataset == 'cifar10-valid': + valid_info = information.get_metrics(dataset, 'x-valid') + str2 = '{:14s} train : [{:}], valid : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy'])) + elif dataset == 'cifar10': + test__info = information.get_metrics(dataset, 'ori-test') + str2 = '{:14s} train : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + else: + valid_info = information.get_metrics(dataset, 'x-valid') + test__info = information.get_metrics(dataset, 'x-test') + str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + strings += [str1, str2] + if show: print('\n'.join(strings)) + return strings + + +""" +This is the class for the API of NAS-Bench-201. +""" +class NASBench201API(NASBenchMetaAPI): + + """ The initialization function that takes the dataset file path (or a dict loaded from that path) as input. """ + def __init__(self, file_path_or_dict: Optional[Union[Text, Dict]]=None, + verbose: bool=True): + self.filename = None + self.reset_time() + if file_path_or_dict is None: + file_path_or_dict = os.path.join(os.environ['TORCH_HOME'], ALL_BENCHMARK_FILES[-1]) + print ('Try to use the default NAS-Bench-201 path from {:}.'.format(file_path_or_dict)) + if isinstance(file_path_or_dict, str) or isinstance(file_path_or_dict, Path): + file_path_or_dict = str(file_path_or_dict) + if verbose: print('try to create the NAS-Bench-201 api from {:}'.format(file_path_or_dict)) + assert os.path.isfile(file_path_or_dict), 'invalid path : {:}'.format(file_path_or_dict) + self.filename = Path(file_path_or_dict).name + file_path_or_dict = torch.load(file_path_or_dict, map_location='cpu') + elif isinstance(file_path_or_dict, dict): + file_path_or_dict = copy.deepcopy(file_path_or_dict) + else: raise ValueError('invalid type : {:} not in [str, dict]'.format(type(file_path_or_dict))) + assert isinstance(file_path_or_dict, dict), 'It should be a dict instead of {:}'.format(type(file_path_or_dict)) + self.verbose = verbose # [TODO] a flag indicating whether to print more logs + keys = ('meta_archs', 'arch2infos', 'evaluated_indexes') + for key in keys: assert key in file_path_or_dict, 'Can not find key[{:}] in the dict'.format(key) + self.meta_archs = copy.deepcopy( file_path_or_dict['meta_archs'] ) + # This is a dict mapping each architecture to a dict, where the key is #epochs and the value is ArchResults + self.arch2infos_dict = OrderedDict() + self._avaliable_hps = set(['12', '200']) + for xkey in sorted(list(file_path_or_dict['arch2infos'].keys())): + all_info = file_path_or_dict['arch2infos'][xkey] + hp2archres = OrderedDict() + # self.arch2infos_less[xkey] = ArchResults.create_from_state_dict( all_info['less'] ) + # self.arch2infos_full[xkey] = ArchResults.create_from_state_dict( all_info['full'] ) + hp2archres['12'] = ArchResults.create_from_state_dict(all_info['less']) + hp2archres['200'] = ArchResults.create_from_state_dict(all_info['full']) + self.arch2infos_dict[xkey] = hp2archres + self.evaluated_indexes = sorted(list(file_path_or_dict['evaluated_indexes'])) + self.archstr2index = {} + for idx, arch in enumerate(self.meta_archs): + assert arch not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch]) + self.archstr2index[ arch ] = idx + + def reload(self, archive_root: Text = None, index: int = None): + """Overwrite all information of the 'index'-th architecture in the search space. + It will load its data from 'archive_root'. + """ + if archive_root is None: + archive_root = os.path.join(os.environ['TORCH_HOME'], ALL_ARCHIVE_DIRS[-1]) + assert os.path.isdir(archive_root), 'invalid directory : {:}'.format(archive_root) + if index is None: + indexes = list(range(len(self))) + else: + indexes = [index] + for idx in indexes: + assert 0 <= idx < len(self.meta_archs), 'invalid index of {:}'.format(idx) + xfile_path = os.path.join(archive_root, '{:06d}-FULL.pth'.format(idx)) + assert os.path.isfile(xfile_path), 'invalid data path : {:}'.format(xfile_path) + xdata = torch.load(xfile_path, map_location='cpu') + assert isinstance(xdata, dict) and 'full' in xdata and 'less' in xdata, 'invalid format of data in {:}'.format(xfile_path) + hp2archres = OrderedDict() + hp2archres['12'] = ArchResults.create_from_state_dict(xdata['less']) + hp2archres['200'] = ArchResults.create_from_state_dict(xdata['full']) + self.arch2infos_dict[idx] = hp2archres + + def query_info_str_by_arch(self, arch, hp: Text='12'): + """ This function is used to query the information of a specific architecture + 'arch' can be an architecture index or an architecture string + When hp=12, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/12E.config' + When hp=200, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/200E.config' + The difference between these three configurations are the number of training epochs. + """ + if self.verbose: + print('Call query_info_str_by_arch with arch={:} and hp={:}'.format(arch, hp)) + return self._query_info_str_by_arch(arch, hp, print_information) + + # obtain the metric for the `index`-th architecture + # `dataset` indicates the dataset: + # 'cifar10-valid' : using the proposed train set of CIFAR-10 as the training set + # 'cifar10' : using the proposed train+valid set of CIFAR-10 as the training set + # 'cifar100' : using the proposed train set of CIFAR-100 as the training set + # 'ImageNet16-120' : using the proposed train set of ImageNet-16-120 as the training set + # `iepoch` indicates the index of training epochs from 0 to 11/199. + # When iepoch=None, it will return the metric for the last training epoch + # When iepoch=11, it will return the metric for the 11-th training epoch (starting from 0) + # `use_12epochs_result` indicates different hyper-parameters for training + # When use_12epochs_result=True, it trains the network with 12 epochs and the LR decayed from 0.1 to 0 within 12 epochs + # When use_12epochs_result=False, it trains the network with 200 epochs and the LR decayed from 0.1 to 0 within 200 epochs + # `is_random` + # When is_random=True, the performance of a random architecture will be returned + # When is_random=False, the performanceo of all trials will be averaged. + def get_more_info(self, index, dataset, iepoch=None, hp='12', is_random=True): + if self.verbose: + print('Call the get_more_info function with index={:}, dataset={:}, iepoch={:}, hp={:}, and is_random={:}.'.format(index, dataset, iepoch, hp, is_random)) + index = self.query_index_by_arch(index) # To avoid the input is a string or an instance of a arch object + if index not in self.arch2infos_dict: + raise ValueError('Did not find {:} from arch2infos_dict.'.format(index)) + archresult = self.arch2infos_dict[index][str(hp)] + # if randomly select one trial, select the seed at first + if isinstance(is_random, bool) and is_random: + seeds = archresult.get_dataset_seeds(dataset) + is_random = random.choice(seeds) + # collect the training information + train_info = archresult.get_metrics(dataset, 'train', iepoch=iepoch, is_random=is_random) + total = train_info['iepoch'] + 1 + xinfo = {'train-loss' : train_info['loss'], + 'train-accuracy': train_info['accuracy'], + 'train-per-time': train_info['all_time'] / total if train_info['all_time'] is not None else None, + 'train-all-time': train_info['all_time']} + # collect the evaluation information + if dataset == 'cifar10-valid': + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + try: + test_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + except: + test_info = None + valtest_info = None + else: + try: # collect results on the proposed test set + if dataset == 'cifar10': + test_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + test_info = archresult.get_metrics(dataset, 'x-test', iepoch=iepoch, is_random=is_random) + except: + test_info = None + try: # collect results on the proposed validation set + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + except: + valid_info = None + try: + if dataset != 'cifar10': + valtest_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + valtest_info = None + except: + valtest_info = None + if valid_info is not None: + xinfo['valid-loss'] = valid_info['loss'] + xinfo['valid-accuracy'] = valid_info['accuracy'] + xinfo['valid-per-time'] = valid_info['all_time'] / total if valid_info['all_time'] is not None else None + xinfo['valid-all-time'] = valid_info['all_time'] + if test_info is not None: + xinfo['test-loss'] = test_info['loss'] + xinfo['test-accuracy'] = test_info['accuracy'] + xinfo['test-per-time'] = test_info['all_time'] / total if test_info['all_time'] is not None else None + xinfo['test-all-time'] = test_info['all_time'] + if valtest_info is not None: + xinfo['valtest-loss'] = valtest_info['loss'] + xinfo['valtest-accuracy'] = valtest_info['accuracy'] + xinfo['valtest-per-time'] = valtest_info['all_time'] / total if valtest_info['all_time'] is not None else None + xinfo['valtest-all-time'] = valtest_info['all_time'] + return xinfo + + def show(self, index: int = -1) -> None: + """This function will print the information of a specific (or all) architecture(s).""" + self._show(index, print_information) + + @staticmethod + def str2lists(arch_str: Text) -> List[tuple]: + """ + This function shows how to read the string-based architecture encoding. + It is the same as the `str2structure` func in `AutoDL-Projects/lib/models/cell_searchs/genotypes.py` + + :param + arch_str: the input is a string indicates the architecture topology, such as + |nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2| + :return: a list of tuple, contains multiple (op, input_node_index) pairs. + + :usage + arch = api.str2lists( '|nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2|' ) + print ('there are {:} nodes in this arch'.format(len(arch)+1)) # arch is a list + for i, node in enumerate(arch): + print('the {:}-th node is the sum of these {:} nodes with op: {:}'.format(i+1, len(node), node)) + """ + node_strs = arch_str.split('+') + genotypes = [] + for i, node_str in enumerate(node_strs): + inputs = list(filter(lambda x: x != '', node_str.split('|'))) + for xinput in inputs: assert len(xinput.split('~')) == 2, 'invalid input length : {:}'.format(xinput) + inputs = ( xi.split('~') for xi in inputs ) + input_infos = tuple( (op, int(IDX)) for (op, IDX) in inputs) + genotypes.append( input_infos ) + return genotypes + + @staticmethod + def str2matrix(arch_str: Text, + search_space: List[Text] = ['none', 'skip_connect', 'nor_conv_1x1', 'nor_conv_3x3', 'avg_pool_3x3']) -> np.ndarray: + """ + This func shows how to convert the string-based architecture encoding to the encoding strategy in NAS-Bench-101. + + :param + arch_str: the input is a string indicates the architecture topology, such as + |nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2| + search_space: a list of operation string, the default list is the search space for NAS-Bench-201 + the default value should be be consistent with this line https://github.com/D-X-Y/AutoDL-Projects/blob/master/lib/models/cell_operations.py#L24 + :return + the numpy matrix (2-D np.ndarray) representing the DAG of this architecture topology + :usage + matrix = api.str2matrix( '|nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2|' ) + This matrix is 4-by-4 matrix representing a cell with 4 nodes (only the lower left triangle is useful). + [ [0, 0, 0, 0], # the first line represents the input (0-th) node + [2, 0, 0, 0], # the second line represents the 1-st node, is calculated by 2-th-op( 0-th-node ) + [0, 0, 0, 0], # the third line represents the 2-nd node, is calculated by 0-th-op( 0-th-node ) + 0-th-op( 1-th-node ) + [0, 0, 1, 0] ] # the fourth line represents the 3-rd node, is calculated by 0-th-op( 0-th-node ) + 0-th-op( 1-th-node ) + 1-th-op( 2-th-node ) + In NAS-Bench-201 search space, 0-th-op is 'none', 1-th-op is 'skip_connect', + 2-th-op is 'nor_conv_1x1', 3-th-op is 'nor_conv_3x3', 4-th-op is 'avg_pool_3x3'. + :(NOTE) + If a node has two input-edges from the same node, this function does not work. One edge will be overlapped. + """ + node_strs = arch_str.split('+') + num_nodes = len(node_strs) + 1 + matrix = np.zeros((num_nodes, num_nodes)) + for i, node_str in enumerate(node_strs): + inputs = list(filter(lambda x: x != '', node_str.split('|'))) + for xinput in inputs: assert len(xinput.split('~')) == 2, 'invalid input length : {:}'.format(xinput) + for xi in inputs: + op, idx = xi.split('~') + if op not in search_space: raise ValueError('this op ({:}) is not in {:}'.format(op, search_space)) + op_idx, node_idx = search_space.index(op), int(idx) + matrix[i+1, node_idx] = op_idx + return matrix + diff --git a/autodl/nas_201_api/api_301.py b/autodl/nas_201_api/api_301.py new file mode 100644 index 0000000..005dc05 --- /dev/null +++ b/autodl/nas_201_api/api_301.py @@ -0,0 +1,222 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2020.06 # +############################################################################################ +# NAS-Bench-301, coming soon. +############################################################################################ +# The history of benchmark files: +# [2020.06.30] NAS-Bench-301-v1_0 +# +import os, copy, random, torch, numpy as np +from pathlib import Path +from typing import List, Text, Union, Dict, Optional +from collections import OrderedDict, defaultdict +from .api_utils import ArchResults +from .api_utils import NASBenchMetaAPI +from .api_utils import remap_dataset_set_names + + +ALL_BENCHMARK_FILES = ['NAS-Bench-301-v1_0-363be7.pth'] +ALL_ARCHIVE_DIRS = ['NAS-Bench-301-v1_0-archive'] + + +def print_information(information, extra_info=None, show=False): + dataset_names = information.get_dataset_names() + strings = [information.arch_str, 'datasets : {:}, extra-info : {:}'.format(dataset_names, extra_info)] + def metric2str(loss, acc): + return 'loss = {:.3f} & top1 = {:.2f}%'.format(loss, acc) + + for ida, dataset in enumerate(dataset_names): + metric = information.get_compute_costs(dataset) + flop, param, latency = metric['flops'], metric['params'], metric['latency'] + str1 = '{:14s} FLOP={:6.2f} M, Params={:.3f} MB, latency={:} ms.'.format(dataset, flop, param, '{:.2f}'.format(latency*1000) if latency is not None and latency > 0 else None) + train_info = information.get_metrics(dataset, 'train') + if dataset == 'cifar10-valid': + valid_info = information.get_metrics(dataset, 'x-valid') + test__info = information.get_metrics(dataset, 'ori-test') + str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format( + dataset, metric2str(train_info['loss'], train_info['accuracy']), + metric2str(valid_info['loss'], valid_info['accuracy']), + metric2str(test__info['loss'], test__info['accuracy'])) + elif dataset == 'cifar10': + test__info = information.get_metrics(dataset, 'ori-test') + str2 = '{:14s} train : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + else: + valid_info = information.get_metrics(dataset, 'x-valid') + test__info = information.get_metrics(dataset, 'x-test') + str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + strings += [str1, str2] + if show: print('\n'.join(strings)) + return strings + + +""" +This is the class for the API of NAS-Bench-301. +""" +class NASBench301API(NASBenchMetaAPI): + + """ The initialization function that takes the dataset file path (or a dict loaded from that path) as input. """ + def __init__(self, file_path_or_dict: Optional[Union[Text, Dict]]=None, verbose: bool=True): + self.filename = None + self.reset_time() + if file_path_or_dict is None: + file_path_or_dict = os.path.join(os.environ['TORCH_HOME'], ALL_BENCHMARK_FILES[-1]) + print ('Try to use the default NAS-Bench-301 path from {:}.'.format(file_path_or_dict)) + if isinstance(file_path_or_dict, str) or isinstance(file_path_or_dict, Path): + file_path_or_dict = str(file_path_or_dict) + if verbose: print('try to create the NAS-Bench-201 api from {:}'.format(file_path_or_dict)) + assert os.path.isfile(file_path_or_dict), 'invalid path : {:}'.format(file_path_or_dict) + self.filename = Path(file_path_or_dict).name + file_path_or_dict = torch.load(file_path_or_dict, map_location='cpu') + elif isinstance(file_path_or_dict, dict): + file_path_or_dict = copy.deepcopy( file_path_or_dict ) + else: raise ValueError('invalid type : {:} not in [str, dict]'.format(type(file_path_or_dict))) + assert isinstance(file_path_or_dict, dict), 'It should be a dict instead of {:}'.format(type(file_path_or_dict)) + self.verbose = verbose # [TODO] a flag indicating whether to print more logs + keys = ('meta_archs', 'arch2infos', 'evaluated_indexes') + for key in keys: assert key in file_path_or_dict, 'Can not find key[{:}] in the dict'.format(key) + self.meta_archs = copy.deepcopy( file_path_or_dict['meta_archs'] ) + # This is a dict mapping each architecture to a dict, where the key is #epochs and the value is ArchResults + self.arch2infos_dict = OrderedDict() + self._avaliable_hps = set() + for xkey in sorted(list(file_path_or_dict['arch2infos'].keys())): + all_infos = file_path_or_dict['arch2infos'][xkey] + hp2archres = OrderedDict() + for hp_key, results in all_infos.items(): + hp2archres[hp_key] = ArchResults.create_from_state_dict(results) + self._avaliable_hps.add(hp_key) # save the avaliable hyper-parameter + self.arch2infos_dict[xkey] = hp2archres + self.evaluated_indexes = sorted(list(file_path_or_dict['evaluated_indexes'])) + self.archstr2index = {} + for idx, arch in enumerate(self.meta_archs): + assert arch not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch]) + self.archstr2index[ arch ] = idx + if self.verbose: + print('Create NAS-Bench-301 done with {:}/{:} architectures avaliable.'.format(len(self.evaluated_indexes), len(self.meta_archs))) + + def reload(self, archive_root: Text = None, index: int = None): + """Overwrite all information of the 'index'-th architecture in the search space, where the data will be loaded from 'archive_root'. + If index is None, overwrite all ckps. + """ + if self.verbose: + print('Call clear_params with archive_root={:} and index={:}'.format(archive_root, index)) + if archive_root is None: + archive_root = os.path.join(os.environ['TORCH_HOME'], ALL_ARCHIVE_DIRS[-1]) + assert os.path.isdir(archive_root), 'invalid directory : {:}'.format(archive_root) + if index is None: + indexes = list(range(len(self))) + else: + indexes = [index] + for idx in indexes: + assert 0 <= idx < len(self.meta_archs), 'invalid index of {:}'.format(idx) + xfile_path = os.path.join(archive_root, '{:06d}-FULL.pth'.format(idx)) + if not os.path.isfile(xfile_path): + xfile_path = os.path.join(archive_root, '{:d}-FULL.pth'.format(idx)) + assert os.path.isfile(xfile_path), 'invalid data path : {:}'.format(xfile_path) + xdata = torch.load(xfile_path, map_location='cpu') + assert isinstance(xdata, dict), 'invalid format of data in {:}'.format(xfile_path) + + hp2archres = OrderedDict() + for hp_key, results in xdata.items(): + hp2archres[hp_key] = ArchResults.create_from_state_dict(results) + self.arch2infos_dict[idx] = hp2archres + + def query_info_str_by_arch(self, arch, hp: Text='12'): + """ This function is used to query the information of a specific architecture + 'arch' can be an architecture index or an architecture string + When hp=01, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/01E.config' + When hp=12, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/12E.config' + When hp=90, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/90E.config' + The difference between these three configurations are the number of training epochs. + """ + if self.verbose: + print('Call query_info_str_by_arch with arch={:} and hp={:}'.format(arch, hp)) + return self._query_info_str_by_arch(arch, hp, print_information) + + def get_more_info(self, index, dataset: Text, iepoch=None, hp='12', is_random=True): + """This function will return the metric for the `index`-th architecture + `dataset` indicates the dataset: + 'cifar10-valid' : using the proposed train set of CIFAR-10 as the training set + 'cifar10' : using the proposed train+valid set of CIFAR-10 as the training set + 'cifar100' : using the proposed train set of CIFAR-100 as the training set + 'ImageNet16-120' : using the proposed train set of ImageNet-16-120 as the training set + `iepoch` indicates the index of training epochs from 0 to 11/199. + When iepoch=None, it will return the metric for the last training epoch + When iepoch=11, it will return the metric for the 11-th training epoch (starting from 0) + `hp` indicates different hyper-parameters for training + When hp=01, it trains the network with 01 epochs and the LR decayed from 0.1 to 0 within 01 epochs + When hp=12, it trains the network with 01 epochs and the LR decayed from 0.1 to 0 within 12 epochs + When hp=90, it trains the network with 01 epochs and the LR decayed from 0.1 to 0 within 90 epochs + `is_random` + When is_random=True, the performance of a random architecture will be returned + When is_random=False, the performanceo of all trials will be averaged. + """ + if self.verbose: + print('Call the get_more_info function with index={:}, dataset={:}, iepoch={:}, hp={:}, and is_random={:}.'.format(index, dataset, iepoch, hp, is_random)) + index = self.query_index_by_arch(index) # To avoid the input is a string or an instance of a arch object + if index not in self.arch2infos_dict: + raise ValueError('Did not find {:} from arch2infos_dict.'.format(index)) + archresult = self.arch2infos_dict[index][str(hp)] + # if randomly select one trial, select the seed at first + if isinstance(is_random, bool) and is_random: + seeds = archresult.get_dataset_seeds(dataset) + is_random = random.choice(seeds) + # collect the training information + train_info = archresult.get_metrics(dataset, 'train', iepoch=iepoch, is_random=is_random) + total = train_info['iepoch'] + 1 + xinfo = {'train-loss' : train_info['loss'], + 'train-accuracy': train_info['accuracy'], + 'train-per-time': train_info['all_time'] / total, + 'train-all-time': train_info['all_time']} + # collect the evaluation information + if dataset == 'cifar10-valid': + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + try: + test_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + except: + test_info = None + valtest_info = None + else: + try: # collect results on the proposed test set + if dataset == 'cifar10': + test_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + test_info = archresult.get_metrics(dataset, 'x-test', iepoch=iepoch, is_random=is_random) + except: + test_info = None + try: # collect results on the proposed validation set + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + except: + valid_info = None + try: + if dataset != 'cifar10': + valtest_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + valtest_info = None + except: + valtest_info = None + if valid_info is not None: + xinfo['valid-loss'] = valid_info['loss'] + xinfo['valid-accuracy'] = valid_info['accuracy'] + xinfo['valid-per-time'] = valid_info['all_time'] / total + xinfo['valid-all-time'] = valid_info['all_time'] + if test_info is not None: + xinfo['test-loss'] = test_info['loss'] + xinfo['test-accuracy'] = test_info['accuracy'] + xinfo['test-per-time'] = test_info['all_time'] / total + xinfo['test-all-time'] = test_info['all_time'] + if valtest_info is not None: + xinfo['valtest-loss'] = valtest_info['loss'] + xinfo['valtest-accuracy'] = valtest_info['accuracy'] + xinfo['valtest-per-time'] = valtest_info['all_time'] / total + xinfo['valtest-all-time'] = valtest_info['all_time'] + return xinfo + + def show(self, index: int = -1) -> None: + """ + This function will print the information of a specific (or all) architecture(s). + + :param index: If the index < 0: it will loop for all architectures and print their information one by one. + else: it will print the information of the 'index'-th architecture. + :return: nothing + """ + self._show(index, print_information) diff --git a/autodl/nas_201_api/api_utils.py b/autodl/nas_201_api/api_utils.py new file mode 100644 index 0000000..9f37160 --- /dev/null +++ b/autodl/nas_201_api/api_utils.py @@ -0,0 +1,750 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +############################################################################################ +# NAS-Bench-201: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 # +############################################################################################ +# In this Python file, we define NASBenchMetaAPI, the abstract class for benchmark APIs. +# We also define the class ArchResults, which contains all information of a single architecture trained by one kind of hyper-parameters on three datasets. +# We also define the class ResultsCount, which contains all information of a single trial for a single architecture. +############################################################################################ +# History: +# [2020.06.30] The first version. +# +import os, abc, copy, random, torch, numpy as np +from pathlib import Path +from typing import List, Text, Union, Dict, Optional +from collections import OrderedDict, defaultdict + + +def remap_dataset_set_names(dataset, metric_on_set, verbose=False): + """re-map the metric_on_set to internal keys""" + if verbose: + print('Call internal function _remap_dataset_set_names with dataset={:} and metric_on_set={:}'.format(dataset, metric_on_set)) + if dataset == 'cifar10' and metric_on_set == 'valid': + dataset, metric_on_set = 'cifar10-valid', 'x-valid' + elif dataset == 'cifar10' and metric_on_set == 'test': + dataset, metric_on_set = 'cifar10', 'ori-test' + elif dataset == 'cifar10' and metric_on_set == 'train': + dataset, metric_on_set = 'cifar10', 'train' + elif (dataset == 'cifar100' or dataset == 'ImageNet16-120') and metric_on_set == 'valid': + metric_on_set = 'x-valid' + elif (dataset == 'cifar100' or dataset == 'ImageNet16-120') and metric_on_set == 'test': + metric_on_set = 'x-test' + if verbose: + print(' return dataset={:} and metric_on_set={:}'.format(dataset, metric_on_set)) + return dataset, metric_on_set + + +class NASBenchMetaAPI(metaclass=abc.ABCMeta): + + @abc.abstractmethod + def __init__(self, file_path_or_dict: Optional[Union[Text, Dict]]=None, verbose: bool=True): + """The initialization function that takes the dataset file path (or a dict loaded from that path) as input.""" + + def __getitem__(self, index: int): + return copy.deepcopy(self.meta_archs[index]) + + def arch(self, index: int): + """Return the topology structure of the `index`-th architecture.""" + if self.verbose: + print('Call the arch function with index={:}'.format(index)) + assert 0 <= index < len(self.meta_archs), 'invalid index : {:} vs. {:}.'.format(index, len(self.meta_archs)) + return copy.deepcopy(self.meta_archs[index]) + + def __len__(self): + return len(self.meta_archs) + + def __repr__(self): + return ('{name}({num}/{total} architectures, file={filename})'.format(name=self.__class__.__name__, num=len(self.evaluated_indexes), total=len(self.meta_archs), filename=self.filename)) + + @property + def avaliable_hps(self): + return list(copy.deepcopy(self._avaliable_hps)) + + @property + def used_time(self): + return self._used_time + + def reset_time(self): + self._used_time = 0 + + def simulate_train_eval(self, arch, dataset, iepoch=None, hp='12', account_time=True): + index = self.query_index_by_arch(arch) + all_names = ('cifar10', 'cifar100', 'ImageNet16-120') + assert dataset in all_names, 'Invalid dataset name : {:} vs {:}'.format(dataset, all_names) + if dataset == 'cifar10': + info = self.get_more_info(index, 'cifar10-valid', iepoch=iepoch, hp=hp, is_random=True) + else: + info = self.get_more_info(index, dataset, iepoch=iepoch, hp=hp, is_random=True) + valid_acc, time_cost = info['valid-accuracy'], info['train-all-time'] + info['valid-per-time'] + latency = self.get_latency(index, dataset) + if account_time: + self._used_time += time_cost + return valid_acc, latency, time_cost, self._used_time + + def random(self): + """Return a random index of all architectures.""" + return random.randint(0, len(self.meta_archs)-1) + + def query_index_by_arch(self, arch): + """ This function is used to query the index of an architecture in the search space. + In the topology search space, the input arch can be an architecture string such as '|nor_conv_3x3~0|+|nor_conv_3x3~0|avg_pool_3x3~1|+|skip_connect~0|nor_conv_3x3~1|skip_connect~2|'; + or an instance that has the 'tostr' function that can generate the architecture string; + or it is directly an architecture index, in this case, we will check whether it is valid or not. + This function will return the index. + If return -1, it means this architecture is not in the search space. + Otherwise, it will return an int in [0, the-number-of-candidates-in-the-search-space). + """ + if self.verbose: + print('Call query_index_by_arch with arch={:}'.format(arch)) + if isinstance(arch, int): + if 0 <= arch < len(self): + return arch + else: + raise ValueError('Invalid architecture index {:} vs [{:}, {:}].'.format(arch, 0, len(self))) + elif isinstance(arch, str): + if arch in self.archstr2index: arch_index = self.archstr2index[ arch ] + else : arch_index = -1 + elif hasattr(arch, 'tostr'): + if arch.tostr() in self.archstr2index: arch_index = self.archstr2index[ arch.tostr() ] + else : arch_index = -1 + else: arch_index = -1 + return arch_index + + def query_by_arch(self, arch, hp): + # This is to make the current version be compatible with the old version. + return self.query_info_str_by_arch(arch, hp) + + @abc.abstractmethod + def reload(self, archive_root: Text = None, index: int = None): + """Overwrite all information of the 'index'-th architecture in the search space, where the data will be loaded from 'archive_root'. + If index is None, overwrite all ckps. + """ + + def clear_params(self, index: int, hp: Optional[Text]=None): + """Remove the architecture's weights to save memory. + :arg + index: the index of the target architecture + hp: a flag to controll how to clear the parameters. + -- None: clear all the weights in '01'/'12'/'90', which indicates the number of training epochs. + -- '01' or '12' or '90': clear all the weights in arch2infos_dict[index][hp]. + """ + if self.verbose: + print('Call clear_params with index={:} and hp={:}'.format(index, hp)) + if hp is None: + for key, result in self.arch2infos_dict[index].items(): + result.clear_params() + else: + if str(hp) not in self.arch2infos_dict[index]: + raise ValueError('The {:}-th architecture only has hyper-parameters of {:} instead of {:}.'.format(index, list(self.arch2infos_dict[index].keys()), hp)) + self.arch2infos_dict[index][str(hp)].clear_params() + + @abc.abstractmethod + def query_info_str_by_arch(self, arch, hp: Text='12'): + """This function is used to query the information of a specific architecture.""" + + def _query_info_str_by_arch(self, arch, hp: Text='12', print_information=None): + arch_index = self.query_index_by_arch(arch) + if arch_index in self.arch2infos_dict: + if hp not in self.arch2infos_dict[arch_index]: + raise ValueError('The {:}-th architecture only has hyper-parameters of {:} instead of {:}.'.format(index, list(self.arch2infos_dict[arch_index].keys()), hp)) + info = self.arch2infos_dict[arch_index][hp] + strings = print_information(info, 'arch-index={:}'.format(arch_index)) + return '\n'.join(strings) + else: + print ('Find this arch-index : {:}, but this arch is not evaluated.'.format(arch_index)) + return None + + def query_meta_info_by_index(self, arch_index, hp: Text = '12'): + """Return the ArchResults for the 'arch_index'-th architecture. This function is similar to query_by_index.""" + if self.verbose: + print('Call query_meta_info_by_index with arch_index={:}, hp={:}'.format(arch_index, hp)) + if arch_index in self.arch2infos_dict: + if hp not in self.arch2infos_dict[arch_index]: + raise ValueError('The {:}-th architecture only has hyper-parameters of {:} instead of {:}.'.format(arch_index, list(self.arch2infos_dict[arch_index].keys()), hp)) + info = self.arch2infos_dict[arch_index][hp] + else: + raise ValueError('arch_index [{:}] does not in arch2infos'.format(arch_index)) + return copy.deepcopy(info) + + def query_by_index(self, arch_index: int, dataname: Union[None, Text] = None, hp: Text = '12'): + """ This 'query_by_index' function is used to query information with the training of 01 epochs, 12 epochs, 90 epochs, or 200 epochs. + ------ + If hp=01, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/01E.config) + If hp=12, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/12E.config) + If hp=90, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/90E.config) + If hp=200, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/200E.config) + ------ + If dataname is None, return the ArchResults + else, return a dict with all trials on that dataset (the key is the seed) + Options are 'cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'. + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + """ + if self.verbose: + print('Call query_by_index with arch_index={:}, dataname={:}, hp={:}'.format(arch_index, dataname, hp)) + info = self.query_meta_info_by_index(arch_index, hp) + if dataname is None: return info + else: + if dataname not in info.get_dataset_names(): + raise ValueError('invalid dataset-name : {:} vs. {:}'.format(dataname, info.get_dataset_names())) + return info.query(dataname) + + def find_best(self, dataset, metric_on_set, FLOP_max=None, Param_max=None, hp: Text = '12'): + """Find the architecture with the highest accuracy based on some constraints.""" + if self.verbose: + print('Call find_best with dataset={:}, metric_on_set={:}, hp={:} | with #FLOPs < {:} and #Params < {:}'.format(dataset, metric_on_set, hp, FLOP_max, Param_max)) + dataset, metric_on_set = remap_dataset_set_names(dataset, metric_on_set, self.verbose) + best_index, highest_accuracy = -1, None + for i, arch_index in enumerate(self.evaluated_indexes): + arch_info = self.arch2infos_dict[arch_index][hp] + info = arch_info.get_compute_costs(dataset) # the information of costs + flop, param, latency = info['flops'], info['params'], info['latency'] + if FLOP_max is not None and flop > FLOP_max : continue + if Param_max is not None and param > Param_max: continue + xinfo = arch_info.get_metrics(dataset, metric_on_set) # the information of loss and accuracy + loss, accuracy = xinfo['loss'], xinfo['accuracy'] + if best_index == -1: + best_index, highest_accuracy = arch_index, accuracy + elif highest_accuracy < accuracy: + best_index, highest_accuracy = arch_index, accuracy + if self.verbose: + print(' the best architecture : [{:}] {:} with accuracy={:.3f}%'.format(best_index, self.arch(best_index), highest_accuracy)) + return best_index, highest_accuracy + + def get_net_param(self, index, dataset, seed: Optional[int], hp: Text = '12'): + """ + This function is used to obtain the trained weights of the `index`-th architecture on `dataset` with the seed of `seed` + Args [seed]: + -- None : return a dict containing the trained weights of all trials, where each key is a seed and its corresponding value is the weights. + -- a interger : return the weights of a specific trial, whose seed is this interger. + Args [hp]: + -- 01 : train the model by 01 epochs + -- 12 : train the model by 12 epochs + -- 90 : train the model by 90 epochs + -- 200 : train the model by 200 epochs + """ + if self.verbose: + print('Call the get_net_param function with index={:}, dataset={:}, seed={:}, hp={:}'.format(index, dataset, seed, hp)) + info = self.query_meta_info_by_index(index, hp) + return info.get_net_param(dataset, seed) + + def get_net_config(self, index: int, dataset: Text): + """ + This function is used to obtain the configuration for the `index`-th architecture on `dataset`. + Args [dataset] (4 possible options): + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + This function will return a dict. + ========= Some examlpes for using this function: + config = api.get_net_config(128, 'cifar10') + """ + if self.verbose: + print('Call the get_net_config function with index={:}, dataset={:}.'.format(index, dataset)) + if index in self.arch2infos_dict: + info = self.arch2infos_dict[index] + else: + raise ValueError('The arch_index={:} is not in arch2infos_dict.'.format(arch_index)) + info = next(iter(info.values())) + results = info.query(dataset, None) + results = next(iter(results.values())) + return results.get_config(None) + + def get_cost_info(self, index: int, dataset: Text, hp: Text = '12') -> Dict[Text, float]: + """To obtain the cost metric for the `index`-th architecture on a dataset.""" + if self.verbose: + print('Call the get_cost_info function with index={:}, dataset={:}, and hp={:}.'.format(index, dataset, hp)) + info = self.query_meta_info_by_index(index, hp) + return info.get_compute_costs(dataset) + + def get_latency(self, index: int, dataset: Text, hp: Text = '12') -> float: + """ + To obtain the latency of the network (by default it will return the latency with the batch size of 256). + :param index: the index of the target architecture + :param dataset: the dataset name (cifar10-valid, cifar10, cifar100, ImageNet16-120) + :return: return a float value in seconds + """ + if self.verbose: + print('Call the get_latency function with index={:}, dataset={:}, and hp={:}.'.format(index, dataset, hp)) + cost_dict = self.get_cost_info(index, dataset, hp) + return cost_dict['latency'] + + @abc.abstractmethod + def show(self, index=-1): + """This function will print the information of a specific (or all) architecture(s).""" + + def _show(self, index=-1, print_information=None) -> None: + """ + This function will print the information of a specific (or all) architecture(s). + + :param index: If the index < 0: it will loop for all architectures and print their information one by one. + else: it will print the information of the 'index'-th architecture. + :return: nothing + """ + if index < 0: # show all architectures + print(self) + for i, idx in enumerate(self.evaluated_indexes): + print('\n' + '-' * 10 + ' The ({:5d}/{:5d}) {:06d}-th architecture! '.format(i, len(self.evaluated_indexes), idx) + '-'*10) + print('arch : {:}'.format(self.meta_archs[idx])) + for key, result in self.arch2infos_dict[index].items(): + strings = print_information(result) + print('>' * 40 + ' {:03d} epochs '.format(result.get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + print('<' * 40 + '------------' + '<' * 40) + else: + if 0 <= index < len(self.meta_archs): + if index not in self.evaluated_indexes: print('The {:}-th architecture has not been evaluated or not saved.'.format(index)) + else: + arch_info = self.arch2infos_dict[index] + for key, result in self.arch2infos_dict[index].items(): + strings = print_information(result) + print('>' * 40 + ' {:03d} epochs '.format(result.get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + print('<' * 40 + '------------' + '<' * 40) + else: + print('This index ({:}) is out of range (0~{:}).'.format(index, len(self.meta_archs))) + + def statistics(self, dataset: Text, hp: Union[Text, int]) -> Dict[int, int]: + """This function will count the number of total trials.""" + if self.verbose: + print('Call the statistics function with dataset={:} and hp={:}.'.format(dataset, hp)) + valid_datasets = ['cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'] + if dataset not in valid_datasets: + raise ValueError('{:} not in {:}'.format(dataset, valid_datasets)) + nums, hp = defaultdict(lambda: 0), str(hp) + for index in range(len(self)): + archInfo = self.arch2infos_dict[index][hp] + dataset_seed = archInfo.dataset_seed + if dataset not in dataset_seed: + nums[0] += 1 + else: + nums[len(dataset_seed[dataset])] += 1 + return dict(nums) + + +class ArchResults(object): + + def __init__(self, arch_index, arch_str): + self.arch_index = int(arch_index) + self.arch_str = copy.deepcopy(arch_str) + self.all_results = dict() + self.dataset_seed = dict() + self.clear_net_done = False + + def get_compute_costs(self, dataset): + x_seeds = self.dataset_seed[dataset] + results = [self.all_results[ (dataset, seed) ] for seed in x_seeds] + + flops = [result.flop for result in results] + params = [result.params for result in results] + latencies = [result.get_latency() for result in results] + latencies = [x for x in latencies if x > 0] + mean_latency = np.mean(latencies) if len(latencies) > 0 else None + time_infos = defaultdict(list) + for result in results: + time_info = result.get_times() + for key, value in time_info.items(): time_infos[key].append( value ) + + info = {'flops' : np.mean(flops), + 'params' : np.mean(params), + 'latency': mean_latency} + for key, value in time_infos.items(): + if len(value) > 0 and value[0] is not None: + info[key] = np.mean(value) + else: info[key] = None + return info + + def get_metrics(self, dataset, setname, iepoch=None, is_random=False): + """ + This `get_metrics` function is used to obtain obtain the loss, accuracy, etc information on a specific dataset. + If not specify, each set refer to the proposed split in NAS-Bench-201 paper. + If some args return None or raise error, then it is not avaliable. + ======================================== + Args [dataset] (4 possible options): + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + Args [setname] (each dataset has different setnames): + -- When dataset = cifar10-valid, you can use 'train', 'x-valid', 'ori-test' + ------ 'train' : the metric on the training set. + ------ 'x-valid' : the metric on the validation set. + ------ 'ori-test' : the metric on the test set. + -- When dataset = cifar10, you can use 'train', 'ori-test'. + ------ 'train' : the metric on the training + validation set. + ------ 'ori-test' : the metric on the test set. + -- When dataset = cifar100 or ImageNet16-120, you can use 'train', 'ori-test', 'x-valid', 'x-test' + ------ 'train' : the metric on the training set. + ------ 'x-valid' : the metric on the validation set. + ------ 'x-test' : the metric on the test set. + ------ 'ori-test' : the metric on the validation + test set. + Args [iepoch] (None or an integer in [0, the-number-of-total-training-epochs) + ------ None : return the metric after the last training epoch. + ------ an integer i : return the metric after the i-th training epoch. + Args [is_random]: + ------ True : return the metric of a randomly selected trial. + ------ False : return the averaged metric of all avaliable trials. + ------ an integer indicating the 'seed' value : return the metric of a specific trial (whose random seed is 'is_random'). + """ + x_seeds = self.dataset_seed[dataset] + results = [self.all_results[ (dataset, seed) ] for seed in x_seeds] + infos = defaultdict(list) + for result in results: + if setname == 'train': + info = result.get_train(iepoch) + else: + info = result.get_eval(setname, iepoch) + for key, value in info.items(): infos[key].append( value ) + return_info = dict() + if isinstance(is_random, bool) and is_random: # randomly select one + index = random.randint(0, len(results)-1) + for key, value in infos.items(): return_info[key] = value[index] + elif isinstance(is_random, bool) and not is_random: # average + for key, value in infos.items(): + if len(value) > 0 and value[0] is not None: + return_info[key] = np.mean(value) + else: return_info[key] = None + elif isinstance(is_random, int): # specify the seed + if is_random not in x_seeds: raise ValueError('can not find random seed ({:}) from {:}'.format(is_random, x_seeds)) + index = x_seeds.index(is_random) + for key, value in infos.items(): return_info[key] = value[index] + else: + raise ValueError('invalid value for is_random: {:}'.format(is_random)) + return return_info + + def show(self, is_print=False): + return print_information(self, None, is_print) + + def get_dataset_names(self): + return list(self.dataset_seed.keys()) + + def get_dataset_seeds(self, dataset): + return copy.deepcopy( self.dataset_seed[dataset] ) + + def get_net_param(self, dataset: Text, seed: Union[None, int] =None): + """ + This function will return the trained network's weights on the 'dataset'. + :arg + dataset: one of 'cifar10-valid', 'cifar10', 'cifar100', and 'ImageNet16-120'. + seed: an integer indicates the seed value or None that indicates returing all trials. + """ + if seed is None: + x_seeds = self.dataset_seed[dataset] + return {seed: self.all_results[(dataset, seed)].get_net_param() for seed in x_seeds} + else: + xkey = (dataset, seed) + if xkey in self.all_results: + return self.all_results[xkey].get_net_param() + else: + raise ValueError('key={:} not in {:}'.format(xkey, list(self.all_results.keys()))) + + def reset_latency(self, dataset: Text, seed: Union[None, Text], latency: float) -> None: + """This function is used to reset the latency in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].update_latency([latency]) + else: + self.all_results[(dataset, seed)].update_latency([latency]) + + def reset_pseudo_train_times(self, dataset: Text, seed: Union[None, Text], estimated_per_epoch_time: float) -> None: + """This function is used to reset the train-times in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].reset_pseudo_train_times(estimated_per_epoch_time) + else: + self.all_results[(dataset, seed)].reset_pseudo_train_times(estimated_per_epoch_time) + + def reset_pseudo_eval_times(self, dataset: Text, seed: Union[None, Text], eval_name: Text, estimated_per_epoch_time: float) -> None: + """This function is used to reset the eval-times in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].reset_pseudo_eval_times(eval_name, estimated_per_epoch_time) + else: + self.all_results[(dataset, seed)].reset_pseudo_eval_times(eval_name, estimated_per_epoch_time) + + def get_latency(self, dataset: Text) -> float: + """Get the latency of a model on the target dataset. [Timestamp: 2020.03.09]""" + latencies = [] + for seed in self.dataset_seed[dataset]: + latency = self.all_results[(dataset, seed)].get_latency() + if not isinstance(latency, float) or latency <= 0: + raise ValueError('invalid latency of {:} with seed={:} : {:}'.format(dataset, seed, latency)) + latencies.append(latency) + return sum(latencies) / len(latencies) + + def get_total_epoch(self, dataset=None): + """Return the total number of training epochs.""" + if dataset is None: + epochss = [] + for xdata, x_seeds in self.dataset_seed.items(): + epochss += [self.all_results[(xdata, seed)].get_total_epoch() for seed in x_seeds] + elif isinstance(dataset, str): + x_seeds = self.dataset_seed[dataset] + epochss = [self.all_results[(dataset, seed)].get_total_epoch() for seed in x_seeds] + else: + raise ValueError('invalid dataset={:}'.format(dataset)) + if len(set(epochss)) > 1: raise ValueError('Each trial mush have the same number of training epochs : {:}'.format(epochss)) + return epochss[-1] + + def query(self, dataset, seed=None): + """Return the ResultsCount object (containing all information of a single trial) for 'dataset' and 'seed'""" + if seed is None: + x_seeds = self.dataset_seed[dataset] + return {seed: self.all_results[(dataset, seed)] for seed in x_seeds} + else: + return self.all_results[(dataset, seed)] + + def arch_idx_str(self): + return '{:06d}'.format(self.arch_index) + + def update(self, dataset_name, seed, result): + if dataset_name not in self.dataset_seed: + self.dataset_seed[dataset_name] = [] + assert seed not in self.dataset_seed[dataset_name], '{:}-th arch alreadly has this seed ({:}) on {:}'.format(self.arch_index, seed, dataset_name) + self.dataset_seed[ dataset_name ].append( seed ) + self.dataset_seed[ dataset_name ] = sorted( self.dataset_seed[ dataset_name ] ) + assert (dataset_name, seed) not in self.all_results + self.all_results[ (dataset_name, seed) ] = result + self.clear_net_done = False + + def state_dict(self): + state_dict = dict() + for key, value in self.__dict__.items(): + if key == 'all_results': # contain the class of ResultsCount + xvalue = dict() + assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value)) + for _k, _v in value.items(): + assert isinstance(_v, ResultsCount), 'invalid type of value for {:}/{:} : {:}'.format(key, _k, type(_v)) + xvalue[_k] = _v.state_dict() + else: + xvalue = value + state_dict[key] = xvalue + return state_dict + + def load_state_dict(self, state_dict): + new_state_dict = dict() + for key, value in state_dict.items(): + if key == 'all_results': # to convert to the class of ResultsCount + xvalue = dict() + assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value)) + for _k, _v in value.items(): + xvalue[_k] = ResultsCount.create_from_state_dict(_v) + else: xvalue = value + new_state_dict[key] = xvalue + self.__dict__.update(new_state_dict) + + @staticmethod + def create_from_state_dict(state_dict_or_file): + x = ArchResults(-1, -1) + if isinstance(state_dict_or_file, str): # a file path + state_dict = torch.load(state_dict_or_file, map_location='cpu') + elif isinstance(state_dict_or_file, dict): + state_dict = state_dict_or_file + else: + raise ValueError('invalid type of state_dict_or_file : {:}'.format(type(state_dict_or_file))) + x.load_state_dict(state_dict) + return x + + # This function is used to clear the weights saved in each 'result' + # This can help reduce the memory footprint. + def clear_params(self): + for key, result in self.all_results.items(): + del result.net_state_dict + result.net_state_dict = None + self.clear_net_done = True + + def debug_test(self): + """This function is used for me to debug and test, which will call most methods.""" + all_dataset = ['cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'] + for dataset in all_dataset: + print('---->>>> {:}'.format(dataset)) + print('The latency on {:} is {:} s'.format(dataset, self.get_latency(dataset))) + for seed in self.dataset_seed[dataset]: + result = self.all_results[(dataset, seed)] + print(' ==>> result = {:}'.format(result)) + print(' ==>> cost = {:}'.format(result.get_times())) + + def __repr__(self): + return ('{name}(arch-index={index}, arch={arch}, {num} runs, clear={clear})'.format(name=self.__class__.__name__, index=self.arch_index, arch=self.arch_str, num=len(self.all_results), clear=self.clear_net_done)) + + +""" +This class (ResultsCount) is used to save the information of one trial for a single architecture. +I did not write much comment for this class, because it is the lowest-level class in NAS-Bench-201 API, which will be rarely called. +If you have any question regarding this class, please open an issue or email me. +""" +class ResultsCount(object): + + def __init__(self, name, state_dict, train_accs, train_losses, params, flop, arch_config, seed, epochs, latency): + self.name = name + self.net_state_dict = state_dict + self.train_acc1es = copy.deepcopy(train_accs) + self.train_acc5es = None + self.train_losses = copy.deepcopy(train_losses) + self.train_times = None + self.arch_config = copy.deepcopy(arch_config) + self.params = params + self.flop = flop + self.seed = seed + self.epochs = epochs + self.latency = latency + # evaluation results + self.reset_eval() + + def update_train_info(self, train_acc1es, train_acc5es, train_losses, train_times) -> None: + self.train_acc1es = train_acc1es + self.train_acc5es = train_acc5es + self.train_losses = train_losses + self.train_times = train_times + + def reset_pseudo_train_times(self, estimated_per_epoch_time: float) -> None: + """Assign the training times.""" + train_times = OrderedDict() + for i in range(self.epochs): + train_times[i] = estimated_per_epoch_time + self.train_times = train_times + + def reset_pseudo_eval_times(self, eval_name: Text, estimated_per_epoch_time: float) -> None: + """Assign the evaluation times.""" + if eval_name not in self.eval_names: raise ValueError('invalid eval name : {:}'.format(eval_name)) + for i in range(self.epochs): + self.eval_times['{:}@{:}'.format(eval_name,i)] = estimated_per_epoch_time + + def reset_eval(self): + self.eval_names = [] + self.eval_acc1es = {} + self.eval_times = {} + self.eval_losses = {} + + def update_latency(self, latency): + self.latency = copy.deepcopy( latency ) + + def get_latency(self) -> float: + """Return the latency value in seconds. -1 represents not avaliable ; otherwise it should be a float value""" + if self.latency is None: return -1.0 + else: return sum(self.latency) / len(self.latency) + + def update_eval(self, accs, losses, times): # new version + data_names = set([x.split('@')[0] for x in accs.keys()]) + for data_name in data_names: + assert data_name not in self.eval_names, '{:} has already been added into eval-names'.format(data_name) + self.eval_names.append( data_name ) + for iepoch in range(self.epochs): + xkey = '{:}@{:}'.format(data_name, iepoch) + self.eval_acc1es[ xkey ] = accs[ xkey ] + self.eval_losses[ xkey ] = losses[ xkey ] + self.eval_times [ xkey ] = times[ xkey ] + + def update_OLD_eval(self, name, accs, losses): # old version + assert name not in self.eval_names, '{:} has already added'.format(name) + self.eval_names.append( name ) + for iepoch in range(self.epochs): + if iepoch in accs: + self.eval_acc1es['{:}@{:}'.format(name,iepoch)] = accs[iepoch] + self.eval_losses['{:}@{:}'.format(name,iepoch)] = losses[iepoch] + + def __repr__(self): + num_eval = len(self.eval_names) + set_name = '[' + ', '.join(self.eval_names) + ']' + return ('{name}({xname}, arch={arch}, FLOP={flop:.2f}M, Param={param:.3f}MB, seed={seed}, {num_eval} eval-sets: {set_name})'.format(name=self.__class__.__name__, xname=self.name, arch=self.arch_config['arch_str'], flop=self.flop, param=self.params, seed=self.seed, num_eval=num_eval, set_name=set_name)) + + def get_total_epoch(self): + return copy.deepcopy(self.epochs) + + def get_times(self): + """Obtain the information regarding both training and evaluation time.""" + if self.train_times is not None and isinstance(self.train_times, dict): + train_times = list( self.train_times.values() ) + time_info = {'T-train@epoch': np.mean(train_times), 'T-train@total': np.sum(train_times)} + else: + time_info = {'T-train@epoch': None, 'T-train@total': None } + for name in self.eval_names: + try: + xtimes = [self.eval_times['{:}@{:}'.format(name,i)] for i in range(self.epochs)] + time_info['T-{:}@epoch'.format(name)] = np.mean(xtimes) + time_info['T-{:}@total'.format(name)] = np.sum(xtimes) + except: + time_info['T-{:}@epoch'.format(name)] = None + time_info['T-{:}@total'.format(name)] = None + return time_info + + def get_eval_set(self): + return self.eval_names + + # get the training information + def get_train(self, iepoch=None): + if iepoch is None: iepoch = self.epochs-1 + assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs) + if self.train_times is not None: + xtime = self.train_times[iepoch] + atime = sum([self.train_times[i] for i in range(iepoch+1)]) + else: xtime, atime = None, None + return {'iepoch' : iepoch, + 'loss' : self.train_losses[iepoch], + 'accuracy': self.train_acc1es[iepoch], + 'cur_time': xtime, + 'all_time': atime} + + def get_eval(self, name, iepoch=None): + """Get the evaluation information ; there could be multiple evaluation sets (identified by the 'name' argument).""" + if iepoch is None: iepoch = self.epochs-1 + assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs) + def _internal_query(xname): + if isinstance(self.eval_times,dict) and len(self.eval_times) > 0: + xtime = self.eval_times['{:}@{:}'.format(xname, iepoch)] + atime = sum([self.eval_times['{:}@{:}'.format(xname, i)] for i in range(iepoch+1)]) + else: + xtime, atime = None, None + return {'iepoch' : iepoch, + 'loss' : self.eval_losses['{:}@{:}'.format(xname, iepoch)], + 'accuracy': self.eval_acc1es['{:}@{:}'.format(xname, iepoch)], + 'cur_time': xtime, + 'all_time': atime} + if name == 'valid': + return _internal_query('x-valid') + else: + return _internal_query(name) + + def get_net_param(self, clone=False): + if clone: return copy.deepcopy(self.net_state_dict) + else: return self.net_state_dict + + def get_config(self, str2structure): + """This function is used to obtain the config dict for this architecture.""" + if str2structure is None: + # In this case, this is NAS-Bench-301 + if 'name' in self.arch_config and self.arch_config['name'] == 'infer.shape.tiny': + return {'name': 'infer.shape.tiny', 'channels': self.arch_config['channels'], + 'genotype': self.arch_config['genotype'], 'num_classes': self.arch_config['class_num']} + # In this case, this is NAS-Bench-201 + else: + return {'name': 'infer.tiny', 'C': self.arch_config['channel'], + 'N' : self.arch_config['num_cells'], + 'arch_str': self.arch_config['arch_str'], 'num_classes': self.arch_config['class_num']} + else: + # In this case, this is NAS-Bench-301 + if 'name' in self.arch_config and self.arch_config['name'] == 'infer.shape.tiny': + return {'name': 'infer.shape.tiny', 'channels': self.arch_config['channels'], + 'genotype': str2structure(self.arch_config['genotype']), 'num_classes': self.arch_config['class_num']} + # In this case, this is NAS-Bench-201 + else: + return {'name': 'infer.tiny', 'C': self.arch_config['channel'], + 'N' : self.arch_config['num_cells'], + 'genotype': str2structure(self.arch_config['arch_str']), 'num_classes': self.arch_config['class_num']} + + def state_dict(self): + _state_dict = {key: value for key, value in self.__dict__.items()} + return _state_dict + + def load_state_dict(self, state_dict): + self.__dict__.update(state_dict) + + @staticmethod + def create_from_state_dict(state_dict): + x = ResultsCount(None, None, None, None, None, None, None, None, None, None) + x.load_state_dict(state_dict) + return x diff --git a/autodl/procedures/__init__.py b/autodl/procedures/__init__.py new file mode 100644 index 0000000..e9330c2 --- /dev/null +++ b/autodl/procedures/__init__.py @@ -0,0 +1,25 @@ +################################################## +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019 # +################################################## +from .starts import prepare_seed, prepare_logger, get_machine_info, save_checkpoint, copy_checkpoint +from .optimizers import get_optim_scheduler +from .funcs_nasbench import evaluate_for_seed as bench_evaluate_for_seed +from .funcs_nasbench import pure_evaluate as bench_pure_evaluate +from .funcs_nasbench import get_nas_bench_loaders + +def get_procedures(procedure): + from .basic_main import basic_train, basic_valid + from .search_main import search_train, search_valid + from .search_main_v2 import search_train_v2 + from .simple_KD_main import simple_KD_train, simple_KD_valid + + train_funcs = {'basic' : basic_train, \ + 'search': search_train,'Simple-KD': simple_KD_train, \ + 'search-v2': search_train_v2} + valid_funcs = {'basic' : basic_valid, \ + 'search': search_valid,'Simple-KD': simple_KD_valid, \ + 'search-v2': search_valid} + + train_func = train_funcs[procedure] + valid_func = valid_funcs[procedure] + return train_func, valid_func diff --git a/autodl/procedures/basic_main.py b/autodl/procedures/basic_main.py new file mode 100644 index 0000000..ed8cea4 --- /dev/null +++ b/autodl/procedures/basic_main.py @@ -0,0 +1,75 @@ +################################################## +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019 # +################################################## +import os, sys, time, torch +from log_utils import AverageMeter, time_string +from utils import obtain_accuracy + + +def basic_train(xloader, network, criterion, scheduler, optimizer, optim_config, extra_info, print_freq, logger): + loss, acc1, acc5 = procedure(xloader, network, criterion, scheduler, optimizer, 'train', optim_config, extra_info, print_freq, logger) + return loss, acc1, acc5 + + +def basic_valid(xloader, network, criterion, optim_config, extra_info, print_freq, logger): + with torch.no_grad(): + loss, acc1, acc5 = procedure(xloader, network, criterion, None, None, 'valid', None, extra_info, print_freq, logger) + return loss, acc1, acc5 + + +def procedure(xloader, network, criterion, scheduler, optimizer, mode, config, extra_info, print_freq, logger): + data_time, batch_time, losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter() + if mode == 'train': + network.train() + elif mode == 'valid': + network.eval() + else: raise ValueError("The mode is not right : {:}".format(mode)) + + #logger.log('[{:5s}] config :: auxiliary={:}, message={:}'.format(mode, config.auxiliary if hasattr(config, 'auxiliary') else -1, network.module.get_message())) + logger.log('[{:5s}] config :: auxiliary={:}'.format(mode, config.auxiliary if hasattr(config, 'auxiliary') else -1)) + end = time.time() + for i, (inputs, targets) in enumerate(xloader): + if mode == 'train': scheduler.update(None, 1.0 * i / len(xloader)) + # measure data loading time + data_time.update(time.time() - end) + # calculate prediction and loss + targets = targets.cuda(non_blocking=True) + + if mode == 'train': optimizer.zero_grad() + + features, logits = network(inputs) + if isinstance(logits, list): + assert len(logits) == 2, 'logits must has {:} items instead of {:}'.format(2, len(logits)) + logits, logits_aux = logits + else: + logits, logits_aux = logits, None + loss = criterion(logits, targets) + if config is not None and hasattr(config, 'auxiliary') and config.auxiliary > 0: + loss_aux = criterion(logits_aux, targets) + loss += config.auxiliary * loss_aux + + if mode == 'train': + loss.backward() + optimizer.step() + + # record + prec1, prec5 = obtain_accuracy(logits.data, targets.data, topk=(1, 5)) + losses.update(loss.item(), inputs.size(0)) + top1.update (prec1.item(), inputs.size(0)) + top5.update (prec5.item(), inputs.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + + if i % print_freq == 0 or (i+1) == len(xloader): + Sstr = ' {:5s} '.format(mode.upper()) + time_string() + ' [{:}][{:03d}/{:03d}]'.format(extra_info, i, len(xloader)) + if scheduler is not None: + Sstr += ' {:}'.format(scheduler.get_min_info()) + Tstr = 'Time {batch_time.val:.2f} ({batch_time.avg:.2f}) Data {data_time.val:.2f} ({data_time.avg:.2f})'.format(batch_time=batch_time, data_time=data_time) + Lstr = 'Loss {loss.val:.3f} ({loss.avg:.3f}) Prec@1 {top1.val:.2f} ({top1.avg:.2f}) Prec@5 {top5.val:.2f} ({top5.avg:.2f})'.format(loss=losses, top1=top1, top5=top5) + Istr = 'Size={:}'.format(list(inputs.size())) + logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Istr) + + logger.log(' **{mode:5s}** Prec@1 {top1.avg:.2f} Prec@5 {top5.avg:.2f} Error@1 {error1:.2f} Error@5 {error5:.2f} Loss:{loss:.3f}'.format(mode=mode.upper(), top1=top1, top5=top5, error1=100-top1.avg, error5=100-top5.avg, loss=losses.avg)) + return losses.avg, top1.avg, top5.avg diff --git a/autodl/procedures/funcs_nasbench.py b/autodl/procedures/funcs_nasbench.py new file mode 100644 index 0000000..c83e4bf --- /dev/null +++ b/autodl/procedures/funcs_nasbench.py @@ -0,0 +1,203 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +##################################################### +import os, time, copy, torch, pathlib + +import datasets +from config_utils import load_config +from autodl.procedures import prepare_seed, get_optim_scheduler +from autodl.utils import get_model_infos, obtain_accuracy +from autodl.log_utils import AverageMeter, time_string, convert_secs2time +from models import get_cell_based_tiny_net + + +__all__ = ['evaluate_for_seed', 'pure_evaluate', 'get_nas_bench_loaders'] + + +def pure_evaluate(xloader, network, criterion=torch.nn.CrossEntropyLoss()): + data_time, batch_time, batch = AverageMeter(), AverageMeter(), None + losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter() + latencies, device = [], torch.cuda.current_device() + network.eval() + with torch.no_grad(): + end = time.time() + for i, (inputs, targets) in enumerate(xloader): + targets = targets.cuda(device=device, non_blocking=True) + inputs = inputs.cuda(device=device, non_blocking=True) + data_time.update(time.time() - end) + # forward + features, logits = network(inputs) + loss = criterion(logits, targets) + batch_time.update(time.time() - end) + if batch is None or batch == inputs.size(0): + batch = inputs.size(0) + latencies.append( batch_time.val - data_time.val ) + # record loss and accuracy + prec1, prec5 = obtain_accuracy(logits.data, targets.data, topk=(1, 5)) + losses.update(loss.item(), inputs.size(0)) + top1.update (prec1.item(), inputs.size(0)) + top5.update (prec5.item(), inputs.size(0)) + end = time.time() + if len(latencies) > 2: latencies = latencies[1:] + return losses.avg, top1.avg, top5.avg, latencies + + + +def procedure(xloader, network, criterion, scheduler, optimizer, mode: str): + losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter() + if mode == 'train' : network.train() + elif mode == 'valid': network.eval() + else: raise ValueError("The mode is not right : {:}".format(mode)) + device = torch.cuda.current_device() + data_time, batch_time, end = AverageMeter(), AverageMeter(), time.time() + for i, (inputs, targets) in enumerate(xloader): + if mode == 'train': scheduler.update(None, 1.0 * i / len(xloader)) + + targets = targets.cuda(device=device, non_blocking=True) + if mode == 'train': optimizer.zero_grad() + # forward + features, logits = network(inputs) + loss = criterion(logits, targets) + # backward + if mode == 'train': + loss.backward() + optimizer.step() + # record loss and accuracy + prec1, prec5 = obtain_accuracy(logits.data, targets.data, topk=(1, 5)) + losses.update(loss.item(), inputs.size(0)) + top1.update (prec1.item(), inputs.size(0)) + top5.update (prec5.item(), inputs.size(0)) + # count time + batch_time.update(time.time() - end) + end = time.time() + return losses.avg, top1.avg, top5.avg, batch_time.sum + + +def evaluate_for_seed(arch_config, opt_config, train_loader, valid_loaders, seed: int, logger): + + prepare_seed(seed) # random seed + net = get_cell_based_tiny_net(arch_config) + #net = TinyNetwork(arch_config['channel'], arch_config['num_cells'], arch, config.class_num) + flop, param = get_model_infos(net, opt_config.xshape) + logger.log('Network : {:}'.format(net.get_message()), False) + logger.log('{:} Seed-------------------------- {:} --------------------------'.format(time_string(), seed)) + logger.log('FLOP = {:} MB, Param = {:} MB'.format(flop, param)) + # train and valid + optimizer, scheduler, criterion = get_optim_scheduler(net.parameters(), opt_config) + default_device = torch.cuda.current_device() + network = torch.nn.DataParallel(net, device_ids=[default_device]).cuda(device=default_device) + criterion = criterion.cuda(device=default_device) + # start training + start_time, epoch_time, total_epoch = time.time(), AverageMeter(), opt_config.epochs + opt_config.warmup + train_losses, train_acc1es, train_acc5es, valid_losses, valid_acc1es, valid_acc5es = {}, {}, {}, {}, {}, {} + train_times , valid_times, lrs = {}, {}, {} + for epoch in range(total_epoch): + scheduler.update(epoch, 0.0) + lr = min(scheduler.get_lr()) + train_loss, train_acc1, train_acc5, train_tm = procedure(train_loader, network, criterion, scheduler, optimizer, 'train') + train_losses[epoch] = train_loss + train_acc1es[epoch] = train_acc1 + train_acc5es[epoch] = train_acc5 + train_times [epoch] = train_tm + lrs[epoch] = lr + with torch.no_grad(): + for key, xloder in valid_loaders.items(): + valid_loss, valid_acc1, valid_acc5, valid_tm = procedure(xloder , network, criterion, None, None, 'valid') + valid_losses['{:}@{:}'.format(key,epoch)] = valid_loss + valid_acc1es['{:}@{:}'.format(key,epoch)] = valid_acc1 + valid_acc5es['{:}@{:}'.format(key,epoch)] = valid_acc5 + valid_times ['{:}@{:}'.format(key,epoch)] = valid_tm + + # measure elapsed time + epoch_time.update(time.time() - start_time) + start_time = time.time() + need_time = 'Time Left: {:}'.format( convert_secs2time(epoch_time.avg * (total_epoch-epoch-1), True) ) + logger.log('{:} {:} epoch={:03d}/{:03d} :: Train [loss={:.5f}, acc@1={:.2f}%, acc@5={:.2f}%] Valid [loss={:.5f}, acc@1={:.2f}%, acc@5={:.2f}%], lr={:}'.format(time_string(), need_time, epoch, total_epoch, train_loss, train_acc1, train_acc5, valid_loss, valid_acc1, valid_acc5, lr)) + info_seed = {'flop' : flop, + 'param': param, + 'arch_config' : arch_config._asdict(), + 'opt_config' : opt_config._asdict(), + 'total_epoch' : total_epoch , + 'train_losses': train_losses, + 'train_acc1es': train_acc1es, + 'train_acc5es': train_acc5es, + 'train_times' : train_times, + 'valid_losses': valid_losses, + 'valid_acc1es': valid_acc1es, + 'valid_acc5es': valid_acc5es, + 'valid_times' : valid_times, + 'learning_rates': lrs, + 'net_state_dict': net.state_dict(), + 'net_string' : '{:}'.format(net), + 'finish-train': True + } + return info_seed + + +def get_nas_bench_loaders(workers): + + torch.set_num_threads(workers) + + root_dir = (pathlib.Path(__file__).parent / '..' / '..').resolve() + torch_dir = pathlib.Path(os.environ['TORCH_HOME']) + # cifar + cifar_config_path = root_dir / 'configs' / 'nas-benchmark' / 'CIFAR.config' + cifar_config = load_config(cifar_config_path, None, None) + get_datasets = datasets.get_datasets # a function to return the dataset + break_line = '-' * 150 + print ('{:} Create data-loader for all datasets'.format(time_string())) + print (break_line) + TRAIN_CIFAR10, VALID_CIFAR10, xshape, class_num = get_datasets('cifar10', str(torch_dir/'cifar.python'), -1) + print ('original CIFAR-10 : {:} training images and {:} test images : {:} input shape : {:} number of classes'.format(len(TRAIN_CIFAR10), len(VALID_CIFAR10), xshape, class_num)) + cifar10_splits = load_config(root_dir / 'configs' / 'nas-benchmark' / 'cifar-split.txt', None, None) + assert cifar10_splits.train[:10] == [0, 5, 7, 11, 13, 15, 16, 17, 20, 24] and cifar10_splits.valid[:10] == [1, 2, 3, 4, 6, 8, 9, 10, 12, 14] + temp_dataset = copy.deepcopy(TRAIN_CIFAR10) + temp_dataset.transform = VALID_CIFAR10.transform + # data loader + trainval_cifar10_loader = torch.utils.data.DataLoader(TRAIN_CIFAR10, batch_size=cifar_config.batch_size, shuffle=True , num_workers=workers, pin_memory=True) + train_cifar10_loader = torch.utils.data.DataLoader(TRAIN_CIFAR10, batch_size=cifar_config.batch_size, sampler=torch.utils.data.sampler.SubsetRandomSampler(cifar10_splits.train), num_workers=workers, pin_memory=True) + valid_cifar10_loader = torch.utils.data.DataLoader(temp_dataset , batch_size=cifar_config.batch_size, sampler=torch.utils.data.sampler.SubsetRandomSampler(cifar10_splits.valid), num_workers=workers, pin_memory=True) + test__cifar10_loader = torch.utils.data.DataLoader(VALID_CIFAR10, batch_size=cifar_config.batch_size, shuffle=False, num_workers=workers, pin_memory=True) + print ('CIFAR-10 : trval-loader has {:3d} batch with {:} per batch'.format(len(trainval_cifar10_loader), cifar_config.batch_size)) + print ('CIFAR-10 : train-loader has {:3d} batch with {:} per batch'.format(len(train_cifar10_loader), cifar_config.batch_size)) + print ('CIFAR-10 : valid-loader has {:3d} batch with {:} per batch'.format(len(valid_cifar10_loader), cifar_config.batch_size)) + print ('CIFAR-10 : test--loader has {:3d} batch with {:} per batch'.format(len(test__cifar10_loader), cifar_config.batch_size)) + print (break_line) + # CIFAR-100 + TRAIN_CIFAR100, VALID_CIFAR100, xshape, class_num = get_datasets('cifar100', str(torch_dir/'cifar.python'), -1) + print ('original CIFAR-100: {:} training images and {:} test images : {:} input shape : {:} number of classes'.format(len(TRAIN_CIFAR100), len(VALID_CIFAR100), xshape, class_num)) + cifar100_splits = load_config(root_dir / 'configs' / 'nas-benchmark' / 'cifar100-test-split.txt', None, None) + assert cifar100_splits.xvalid[:10] == [1, 3, 4, 5, 8, 10, 13, 14, 15, 16] and cifar100_splits.xtest[:10] == [0, 2, 6, 7, 9, 11, 12, 17, 20, 24] + train_cifar100_loader = torch.utils.data.DataLoader(TRAIN_CIFAR100, batch_size=cifar_config.batch_size, shuffle=True, num_workers=workers, pin_memory=True) + valid_cifar100_loader = torch.utils.data.DataLoader(VALID_CIFAR100, batch_size=cifar_config.batch_size, sampler=torch.utils.data.sampler.SubsetRandomSampler(cifar100_splits.xvalid), num_workers=workers, pin_memory=True) + test__cifar100_loader = torch.utils.data.DataLoader(VALID_CIFAR100, batch_size=cifar_config.batch_size, sampler=torch.utils.data.sampler.SubsetRandomSampler(cifar100_splits.xtest) , num_workers=workers, pin_memory=True) + print ('CIFAR-100 : train-loader has {:3d} batch'.format(len(train_cifar100_loader))) + print ('CIFAR-100 : valid-loader has {:3d} batch'.format(len(valid_cifar100_loader))) + print ('CIFAR-100 : test--loader has {:3d} batch'.format(len(test__cifar100_loader))) + print (break_line) + + imagenet16_config_path = 'configs/nas-benchmark/ImageNet-16.config' + imagenet16_config = load_config(imagenet16_config_path, None, None) + TRAIN_ImageNet16_120, VALID_ImageNet16_120, xshape, class_num = get_datasets('ImageNet16-120', str(torch_dir/'cifar.python'/'ImageNet16'), -1) + print ('original TRAIN_ImageNet16_120: {:} training images and {:} test images : {:} input shape : {:} number of classes'.format(len(TRAIN_ImageNet16_120), len(VALID_ImageNet16_120), xshape, class_num)) + imagenet_splits = load_config(root_dir / 'configs' / 'nas-benchmark' / 'imagenet-16-120-test-split.txt', None, None) + assert imagenet_splits.xvalid[:10] == [1, 2, 3, 6, 7, 8, 9, 12, 16, 18] and imagenet_splits.xtest[:10] == [0, 4, 5, 10, 11, 13, 14, 15, 17, 20] + train_imagenet_loader = torch.utils.data.DataLoader(TRAIN_ImageNet16_120, batch_size=imagenet16_config.batch_size, shuffle=True, num_workers=workers, pin_memory=True) + valid_imagenet_loader = torch.utils.data.DataLoader(VALID_ImageNet16_120, batch_size=imagenet16_config.batch_size, sampler=torch.utils.data.sampler.SubsetRandomSampler(imagenet_splits.xvalid), num_workers=workers, pin_memory=True) + test__imagenet_loader = torch.utils.data.DataLoader(VALID_ImageNet16_120, batch_size=imagenet16_config.batch_size, sampler=torch.utils.data.sampler.SubsetRandomSampler(imagenet_splits.xtest) , num_workers=workers, pin_memory=True) + print ('ImageNet-16-120 : train-loader has {:3d} batch with {:} per batch'.format(len(train_imagenet_loader), imagenet16_config.batch_size)) + print ('ImageNet-16-120 : valid-loader has {:3d} batch with {:} per batch'.format(len(valid_imagenet_loader), imagenet16_config.batch_size)) + print ('ImageNet-16-120 : test--loader has {:3d} batch with {:} per batch'.format(len(test__imagenet_loader), imagenet16_config.batch_size)) + + # 'cifar10', 'cifar100', 'ImageNet16-120' + loaders = {'cifar10@trainval': trainval_cifar10_loader, + 'cifar10@train' : train_cifar10_loader, + 'cifar10@valid' : valid_cifar10_loader, + 'cifar10@test' : test__cifar10_loader, + 'cifar100@train' : train_cifar100_loader, + 'cifar100@valid' : valid_cifar100_loader, + 'cifar100@test' : test__cifar100_loader, + 'ImageNet16-120@train': train_imagenet_loader, + 'ImageNet16-120@valid': valid_imagenet_loader, + 'ImageNet16-120@test' : test__imagenet_loader} + return loaders diff --git a/autodl/procedures/optimizers.py b/autodl/procedures/optimizers.py new file mode 100644 index 0000000..7fe086d --- /dev/null +++ b/autodl/procedures/optimizers.py @@ -0,0 +1,204 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.01 # +##################################################### +import math, torch +import torch.nn as nn +from bisect import bisect_right +from torch.optim import Optimizer + + +class _LRScheduler(object): + + def __init__(self, optimizer, warmup_epochs, epochs): + if not isinstance(optimizer, Optimizer): + raise TypeError('{:} is not an Optimizer'.format(type(optimizer).__name__)) + self.optimizer = optimizer + for group in optimizer.param_groups: + group.setdefault('initial_lr', group['lr']) + self.base_lrs = list(map(lambda group: group['initial_lr'], optimizer.param_groups)) + self.max_epochs = epochs + self.warmup_epochs = warmup_epochs + self.current_epoch = 0 + self.current_iter = 0 + + def extra_repr(self): + return '' + + def __repr__(self): + return ('{name}(warmup={warmup_epochs}, max-epoch={max_epochs}, current::epoch={current_epoch}, iter={current_iter:.2f}'.format(name=self.__class__.__name__, **self.__dict__) + + ', {:})'.format(self.extra_repr())) + + def state_dict(self): + return {key: value for key, value in self.__dict__.items() if key != 'optimizer'} + + def load_state_dict(self, state_dict): + self.__dict__.update(state_dict) + + def get_lr(self): + raise NotImplementedError + + def get_min_info(self): + lrs = self.get_lr() + return '#LR=[{:.6f}~{:.6f}] epoch={:03d}, iter={:4.2f}#'.format(min(lrs), max(lrs), self.current_epoch, self.current_iter) + + def get_min_lr(self): + return min( self.get_lr() ) + + def update(self, cur_epoch, cur_iter): + if cur_epoch is not None: + assert isinstance(cur_epoch, int) and cur_epoch>=0, 'invalid cur-epoch : {:}'.format(cur_epoch) + self.current_epoch = cur_epoch + if cur_iter is not None: + assert isinstance(cur_iter, float) and cur_iter>=0, 'invalid cur-iter : {:}'.format(cur_iter) + self.current_iter = cur_iter + for param_group, lr in zip(self.optimizer.param_groups, self.get_lr()): + param_group['lr'] = lr + + + +class CosineAnnealingLR(_LRScheduler): + + def __init__(self, optimizer, warmup_epochs, epochs, T_max, eta_min): + self.T_max = T_max + self.eta_min = eta_min + super(CosineAnnealingLR, self).__init__(optimizer, warmup_epochs, epochs) + + def extra_repr(self): + return 'type={:}, T-max={:}, eta-min={:}'.format('cosine', self.T_max, self.eta_min) + + def get_lr(self): + lrs = [] + for base_lr in self.base_lrs: + if self.current_epoch >= self.warmup_epochs and self.current_epoch < self.max_epochs: + last_epoch = self.current_epoch - self.warmup_epochs + #if last_epoch < self.T_max: + #if last_epoch < self.max_epochs: + lr = self.eta_min + (base_lr - self.eta_min) * (1 + math.cos(math.pi * last_epoch / self.T_max)) / 2 + #else: + # lr = self.eta_min + (base_lr - self.eta_min) * (1 + math.cos(math.pi * (self.T_max-1.0) / self.T_max)) / 2 + elif self.current_epoch >= self.max_epochs: + lr = self.eta_min + else: + lr = (self.current_epoch / self.warmup_epochs + self.current_iter / self.warmup_epochs) * base_lr + lrs.append( lr ) + return lrs + + + +class MultiStepLR(_LRScheduler): + + def __init__(self, optimizer, warmup_epochs, epochs, milestones, gammas): + assert len(milestones) == len(gammas), 'invalid {:} vs {:}'.format(len(milestones), len(gammas)) + self.milestones = milestones + self.gammas = gammas + super(MultiStepLR, self).__init__(optimizer, warmup_epochs, epochs) + + def extra_repr(self): + return 'type={:}, milestones={:}, gammas={:}, base-lrs={:}'.format('multistep', self.milestones, self.gammas, self.base_lrs) + + def get_lr(self): + lrs = [] + for base_lr in self.base_lrs: + if self.current_epoch >= self.warmup_epochs: + last_epoch = self.current_epoch - self.warmup_epochs + idx = bisect_right(self.milestones, last_epoch) + lr = base_lr + for x in self.gammas[:idx]: lr *= x + else: + lr = (self.current_epoch / self.warmup_epochs + self.current_iter / self.warmup_epochs) * base_lr + lrs.append( lr ) + return lrs + + +class ExponentialLR(_LRScheduler): + + def __init__(self, optimizer, warmup_epochs, epochs, gamma): + self.gamma = gamma + super(ExponentialLR, self).__init__(optimizer, warmup_epochs, epochs) + + def extra_repr(self): + return 'type={:}, gamma={:}, base-lrs={:}'.format('exponential', self.gamma, self.base_lrs) + + def get_lr(self): + lrs = [] + for base_lr in self.base_lrs: + if self.current_epoch >= self.warmup_epochs: + last_epoch = self.current_epoch - self.warmup_epochs + assert last_epoch >= 0, 'invalid last_epoch : {:}'.format(last_epoch) + lr = base_lr * (self.gamma ** last_epoch) + else: + lr = (self.current_epoch / self.warmup_epochs + self.current_iter / self.warmup_epochs) * base_lr + lrs.append( lr ) + return lrs + + +class LinearLR(_LRScheduler): + + def __init__(self, optimizer, warmup_epochs, epochs, max_LR, min_LR): + self.max_LR = max_LR + self.min_LR = min_LR + super(LinearLR, self).__init__(optimizer, warmup_epochs, epochs) + + def extra_repr(self): + return 'type={:}, max_LR={:}, min_LR={:}, base-lrs={:}'.format('LinearLR', self.max_LR, self.min_LR, self.base_lrs) + + def get_lr(self): + lrs = [] + for base_lr in self.base_lrs: + if self.current_epoch >= self.warmup_epochs: + last_epoch = self.current_epoch - self.warmup_epochs + assert last_epoch >= 0, 'invalid last_epoch : {:}'.format(last_epoch) + ratio = (self.max_LR - self.min_LR) * last_epoch / self.max_epochs / self.max_LR + lr = base_lr * (1-ratio) + else: + lr = (self.current_epoch / self.warmup_epochs + self.current_iter / self.warmup_epochs) * base_lr + lrs.append( lr ) + return lrs + + + +class CrossEntropyLabelSmooth(nn.Module): + + def __init__(self, num_classes, epsilon): + super(CrossEntropyLabelSmooth, self).__init__() + self.num_classes = num_classes + self.epsilon = epsilon + self.logsoftmax = nn.LogSoftmax(dim=1) + + def forward(self, inputs, targets): + log_probs = self.logsoftmax(inputs) + targets = torch.zeros_like(log_probs).scatter_(1, targets.unsqueeze(1), 1) + targets = (1 - self.epsilon) * targets + self.epsilon / self.num_classes + loss = (-targets * log_probs).mean(0).sum() + return loss + + + +def get_optim_scheduler(parameters, config): + assert hasattr(config, 'optim') and hasattr(config, 'scheduler') and hasattr(config, 'criterion'), 'config must have optim / scheduler / criterion keys instead of {:}'.format(config) + if config.optim == 'SGD': + optim = torch.optim.SGD(parameters, config.LR, momentum=config.momentum, weight_decay=config.decay, nesterov=config.nesterov) + elif config.optim == 'RMSprop': + optim = torch.optim.RMSprop(parameters, config.LR, momentum=config.momentum, weight_decay=config.decay) + else: + raise ValueError('invalid optim : {:}'.format(config.optim)) + + if config.scheduler == 'cos': + T_max = getattr(config, 'T_max', config.epochs) + scheduler = CosineAnnealingLR(optim, config.warmup, config.epochs, T_max, config.eta_min) + elif config.scheduler == 'multistep': + scheduler = MultiStepLR(optim, config.warmup, config.epochs, config.milestones, config.gammas) + elif config.scheduler == 'exponential': + scheduler = ExponentialLR(optim, config.warmup, config.epochs, config.gamma) + elif config.scheduler == 'linear': + scheduler = LinearLR(optim, config.warmup, config.epochs, config.LR, config.LR_min) + else: + raise ValueError('invalid scheduler : {:}'.format(config.scheduler)) + + if config.criterion == 'Softmax': + criterion = torch.nn.CrossEntropyLoss() + elif config.criterion == 'SmoothSoftmax': + criterion = CrossEntropyLabelSmooth(config.class_num, config.label_smooth) + else: + raise ValueError('invalid criterion : {:}'.format(config.criterion)) + return optim, scheduler, criterion diff --git a/autodl/procedures/search_main.py b/autodl/procedures/search_main.py new file mode 100644 index 0000000..48ed44f --- /dev/null +++ b/autodl/procedures/search_main.py @@ -0,0 +1,126 @@ +################################################## +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019 # +################################################## +import os, sys, time, torch +from log_utils import AverageMeter, time_string +from utils import obtain_accuracy +from models import change_key + + +def get_flop_loss(expected_flop, flop_cur, flop_need, flop_tolerant): + expected_flop = torch.mean( expected_flop ) + + if flop_cur < flop_need - flop_tolerant: # Too Small FLOP + loss = - torch.log( expected_flop ) + #elif flop_cur > flop_need + flop_tolerant: # Too Large FLOP + elif flop_cur > flop_need: # Too Large FLOP + loss = torch.log( expected_flop ) + else: # Required FLOP + loss = None + if loss is None: return 0, 0 + else : return loss, loss.item() + + +def search_train(search_loader, network, criterion, scheduler, base_optimizer, arch_optimizer, optim_config, extra_info, print_freq, logger): + data_time, batch_time = AverageMeter(), AverageMeter() + base_losses, arch_losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter() + arch_cls_losses, arch_flop_losses = AverageMeter(), AverageMeter() + epoch_str, flop_need, flop_weight, flop_tolerant = extra_info['epoch-str'], extra_info['FLOP-exp'], extra_info['FLOP-weight'], extra_info['FLOP-tolerant'] + + network.train() + logger.log('[Search] : {:}, FLOP-Require={:.2f} MB, FLOP-WEIGHT={:.2f}'.format(epoch_str, flop_need, flop_weight)) + end = time.time() + network.apply( change_key('search_mode', 'search') ) + for step, (base_inputs, base_targets, arch_inputs, arch_targets) in enumerate(search_loader): + scheduler.update(None, 1.0 * step / len(search_loader)) + # calculate prediction and loss + base_targets = base_targets.cuda(non_blocking=True) + arch_targets = arch_targets.cuda(non_blocking=True) + # measure data loading time + data_time.update(time.time() - end) + + # update the weights + base_optimizer.zero_grad() + logits, expected_flop = network(base_inputs) + #network.apply( change_key('search_mode', 'basic') ) + #features, logits = network(base_inputs) + base_loss = criterion(logits, base_targets) + base_loss.backward() + base_optimizer.step() + # record + prec1, prec5 = obtain_accuracy(logits.data, base_targets.data, topk=(1, 5)) + base_losses.update(base_loss.item(), base_inputs.size(0)) + top1.update (prec1.item(), base_inputs.size(0)) + top5.update (prec5.item(), base_inputs.size(0)) + + # update the architecture + arch_optimizer.zero_grad() + logits, expected_flop = network(arch_inputs) + flop_cur = network.module.get_flop('genotype', None, None) + flop_loss, flop_loss_scale = get_flop_loss(expected_flop, flop_cur, flop_need, flop_tolerant) + acls_loss = criterion(logits, arch_targets) + arch_loss = acls_loss + flop_loss * flop_weight + arch_loss.backward() + arch_optimizer.step() + + # record + arch_losses.update(arch_loss.item(), arch_inputs.size(0)) + arch_flop_losses.update(flop_loss_scale, arch_inputs.size(0)) + arch_cls_losses.update (acls_loss.item(), arch_inputs.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + if step % print_freq == 0 or (step+1) == len(search_loader): + Sstr = '**TRAIN** ' + time_string() + ' [{:}][{:03d}/{:03d}]'.format(epoch_str, step, len(search_loader)) + Tstr = 'Time {batch_time.val:.2f} ({batch_time.avg:.2f}) Data {data_time.val:.2f} ({data_time.avg:.2f})'.format(batch_time=batch_time, data_time=data_time) + Lstr = 'Base-Loss {loss.val:.3f} ({loss.avg:.3f}) Prec@1 {top1.val:.2f} ({top1.avg:.2f}) Prec@5 {top5.val:.2f} ({top5.avg:.2f})'.format(loss=base_losses, top1=top1, top5=top5) + Vstr = 'Acls-loss {aloss.val:.3f} ({aloss.avg:.3f}) FLOP-Loss {floss.val:.3f} ({floss.avg:.3f}) Arch-Loss {loss.val:.3f} ({loss.avg:.3f})'.format(aloss=arch_cls_losses, floss=arch_flop_losses, loss=arch_losses) + logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Vstr) + #Istr = 'Bsz={:} Asz={:}'.format(list(base_inputs.size()), list(arch_inputs.size())) + #logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Vstr + ' ' + Istr) + #print(network.module.get_arch_info()) + #print(network.module.width_attentions[0]) + #print(network.module.width_attentions[1]) + + logger.log(' **TRAIN** Prec@1 {top1.avg:.2f} Prec@5 {top5.avg:.2f} Error@1 {error1:.2f} Error@5 {error5:.2f} Base-Loss:{baseloss:.3f}, Arch-Loss={archloss:.3f}'.format(top1=top1, top5=top5, error1=100-top1.avg, error5=100-top5.avg, baseloss=base_losses.avg, archloss=arch_losses.avg)) + return base_losses.avg, arch_losses.avg, top1.avg, top5.avg + + + +def search_valid(xloader, network, criterion, extra_info, print_freq, logger): + data_time, batch_time, losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter() + + network.eval() + network.apply( change_key('search_mode', 'search') ) + end = time.time() + #logger.log('Starting evaluating {:}'.format(epoch_info)) + with torch.no_grad(): + for i, (inputs, targets) in enumerate(xloader): + # measure data loading time + data_time.update(time.time() - end) + # calculate prediction and loss + targets = targets.cuda(non_blocking=True) + + logits, expected_flop = network(inputs) + loss = criterion(logits, targets) + # record + prec1, prec5 = obtain_accuracy(logits.data, targets.data, topk=(1, 5)) + losses.update(loss.item(), inputs.size(0)) + top1.update (prec1.item(), inputs.size(0)) + top5.update (prec5.item(), inputs.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + + if i % print_freq == 0 or (i+1) == len(xloader): + Sstr = '**VALID** ' + time_string() + ' [{:}][{:03d}/{:03d}]'.format(extra_info, i, len(xloader)) + Tstr = 'Time {batch_time.val:.2f} ({batch_time.avg:.2f}) Data {data_time.val:.2f} ({data_time.avg:.2f})'.format(batch_time=batch_time, data_time=data_time) + Lstr = 'Loss {loss.val:.3f} ({loss.avg:.3f}) Prec@1 {top1.val:.2f} ({top1.avg:.2f}) Prec@5 {top5.val:.2f} ({top5.avg:.2f})'.format(loss=losses, top1=top1, top5=top5) + Istr = 'Size={:}'.format(list(inputs.size())) + logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Istr) + + logger.log(' **VALID** Prec@1 {top1.avg:.2f} Prec@5 {top5.avg:.2f} Error@1 {error1:.2f} Error@5 {error5:.2f} Loss:{loss:.3f}'.format(top1=top1, top5=top5, error1=100-top1.avg, error5=100-top5.avg, loss=losses.avg)) + + return losses.avg, top1.avg, top5.avg diff --git a/autodl/procedures/search_main_v2.py b/autodl/procedures/search_main_v2.py new file mode 100644 index 0000000..46707ef --- /dev/null +++ b/autodl/procedures/search_main_v2.py @@ -0,0 +1,87 @@ +################################################## +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019 # +################################################## +import os, sys, time, torch +from log_utils import AverageMeter, time_string +from utils import obtain_accuracy +from models import change_key + + +def get_flop_loss(expected_flop, flop_cur, flop_need, flop_tolerant): + expected_flop = torch.mean( expected_flop ) + + if flop_cur < flop_need - flop_tolerant: # Too Small FLOP + loss = - torch.log( expected_flop ) + #elif flop_cur > flop_need + flop_tolerant: # Too Large FLOP + elif flop_cur > flop_need: # Too Large FLOP + loss = torch.log( expected_flop ) + else: # Required FLOP + loss = None + if loss is None: return 0, 0 + else : return loss, loss.item() + + +def search_train_v2(search_loader, network, criterion, scheduler, base_optimizer, arch_optimizer, optim_config, extra_info, print_freq, logger): + data_time, batch_time = AverageMeter(), AverageMeter() + base_losses, arch_losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter() + arch_cls_losses, arch_flop_losses = AverageMeter(), AverageMeter() + epoch_str, flop_need, flop_weight, flop_tolerant = extra_info['epoch-str'], extra_info['FLOP-exp'], extra_info['FLOP-weight'], extra_info['FLOP-tolerant'] + + network.train() + logger.log('[Search] : {:}, FLOP-Require={:.2f} MB, FLOP-WEIGHT={:.2f}'.format(epoch_str, flop_need, flop_weight)) + end = time.time() + network.apply( change_key('search_mode', 'search') ) + for step, (base_inputs, base_targets, arch_inputs, arch_targets) in enumerate(search_loader): + scheduler.update(None, 1.0 * step / len(search_loader)) + # calculate prediction and loss + base_targets = base_targets.cuda(non_blocking=True) + arch_targets = arch_targets.cuda(non_blocking=True) + # measure data loading time + data_time.update(time.time() - end) + + # update the weights + base_optimizer.zero_grad() + logits, expected_flop = network(base_inputs) + base_loss = criterion(logits, base_targets) + base_loss.backward() + base_optimizer.step() + # record + prec1, prec5 = obtain_accuracy(logits.data, base_targets.data, topk=(1, 5)) + base_losses.update(base_loss.item(), base_inputs.size(0)) + top1.update (prec1.item(), base_inputs.size(0)) + top5.update (prec5.item(), base_inputs.size(0)) + + # update the architecture + arch_optimizer.zero_grad() + logits, expected_flop = network(arch_inputs) + flop_cur = network.module.get_flop('genotype', None, None) + flop_loss, flop_loss_scale = get_flop_loss(expected_flop, flop_cur, flop_need, flop_tolerant) + acls_loss = criterion(logits, arch_targets) + arch_loss = acls_loss + flop_loss * flop_weight + arch_loss.backward() + arch_optimizer.step() + + # record + arch_losses.update(arch_loss.item(), arch_inputs.size(0)) + arch_flop_losses.update(flop_loss_scale, arch_inputs.size(0)) + arch_cls_losses.update (acls_loss.item(), arch_inputs.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + if step % print_freq == 0 or (step+1) == len(search_loader): + Sstr = '**TRAIN** ' + time_string() + ' [{:}][{:03d}/{:03d}]'.format(epoch_str, step, len(search_loader)) + Tstr = 'Time {batch_time.val:.2f} ({batch_time.avg:.2f}) Data {data_time.val:.2f} ({data_time.avg:.2f})'.format(batch_time=batch_time, data_time=data_time) + Lstr = 'Base-Loss {loss.val:.3f} ({loss.avg:.3f}) Prec@1 {top1.val:.2f} ({top1.avg:.2f}) Prec@5 {top5.val:.2f} ({top5.avg:.2f})'.format(loss=base_losses, top1=top1, top5=top5) + Vstr = 'Acls-loss {aloss.val:.3f} ({aloss.avg:.3f}) FLOP-Loss {floss.val:.3f} ({floss.avg:.3f}) Arch-Loss {loss.val:.3f} ({loss.avg:.3f})'.format(aloss=arch_cls_losses, floss=arch_flop_losses, loss=arch_losses) + logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Vstr) + #num_bytes = torch.cuda.max_memory_allocated( next(network.parameters()).device ) * 1.0 + #logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Vstr + ' GPU={:.2f}MB'.format(num_bytes/1e6)) + #Istr = 'Bsz={:} Asz={:}'.format(list(base_inputs.size()), list(arch_inputs.size())) + #logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Vstr + ' ' + Istr) + #print(network.module.get_arch_info()) + #print(network.module.width_attentions[0]) + #print(network.module.width_attentions[1]) + + logger.log(' **TRAIN** Prec@1 {top1.avg:.2f} Prec@5 {top5.avg:.2f} Error@1 {error1:.2f} Error@5 {error5:.2f} Base-Loss:{baseloss:.3f}, Arch-Loss={archloss:.3f}'.format(top1=top1, top5=top5, error1=100-top1.avg, error5=100-top5.avg, baseloss=base_losses.avg, archloss=arch_losses.avg)) + return base_losses.avg, arch_losses.avg, top1.avg, top5.avg diff --git a/autodl/procedures/simple_KD_main.py b/autodl/procedures/simple_KD_main.py new file mode 100644 index 0000000..5ad8c3b --- /dev/null +++ b/autodl/procedures/simple_KD_main.py @@ -0,0 +1,94 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.01 # +##################################################### +import os, sys, time, torch +import torch.nn.functional as F +# our modules +from log_utils import AverageMeter, time_string +from utils import obtain_accuracy + + +def simple_KD_train(xloader, teacher, network, criterion, scheduler, optimizer, optim_config, extra_info, print_freq, logger): + loss, acc1, acc5 = procedure(xloader, teacher, network, criterion, scheduler, optimizer, 'train', optim_config, extra_info, print_freq, logger) + return loss, acc1, acc5 + +def simple_KD_valid(xloader, teacher, network, criterion, optim_config, extra_info, print_freq, logger): + with torch.no_grad(): + loss, acc1, acc5 = procedure(xloader, teacher, network, criterion, None, None, 'valid', optim_config, extra_info, print_freq, logger) + return loss, acc1, acc5 + + +def loss_KD_fn(criterion, student_logits, teacher_logits, studentFeatures, teacherFeatures, targets, alpha, temperature): + basic_loss = criterion(student_logits, targets) * (1. - alpha) + log_student= F.log_softmax(student_logits / temperature, dim=1) + sof_teacher= F.softmax (teacher_logits / temperature, dim=1) + KD_loss = F.kl_div(log_student, sof_teacher, reduction='batchmean') * (alpha * temperature * temperature) + return basic_loss + KD_loss + + +def procedure(xloader, teacher, network, criterion, scheduler, optimizer, mode, config, extra_info, print_freq, logger): + data_time, batch_time, losses, top1, top5 = AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter(), AverageMeter() + Ttop1, Ttop5 = AverageMeter(), AverageMeter() + if mode == 'train': + network.train() + elif mode == 'valid': + network.eval() + else: raise ValueError("The mode is not right : {:}".format(mode)) + teacher.eval() + + logger.log('[{:5s}] config :: auxiliary={:}, KD :: [alpha={:.2f}, temperature={:.2f}]'.format(mode, config.auxiliary if hasattr(config, 'auxiliary') else -1, config.KD_alpha, config.KD_temperature)) + end = time.time() + for i, (inputs, targets) in enumerate(xloader): + if mode == 'train': scheduler.update(None, 1.0 * i / len(xloader)) + # measure data loading time + data_time.update(time.time() - end) + # calculate prediction and loss + targets = targets.cuda(non_blocking=True) + + if mode == 'train': optimizer.zero_grad() + + student_f, logits = network(inputs) + if isinstance(logits, list): + assert len(logits) == 2, 'logits must has {:} items instead of {:}'.format(2, len(logits)) + logits, logits_aux = logits + else: + logits, logits_aux = logits, None + with torch.no_grad(): + teacher_f, teacher_logits = teacher(inputs) + + loss = loss_KD_fn(criterion, logits, teacher_logits, student_f, teacher_f, targets, config.KD_alpha, config.KD_temperature) + if config is not None and hasattr(config, 'auxiliary') and config.auxiliary > 0: + loss_aux = criterion(logits_aux, targets) + loss += config.auxiliary * loss_aux + + if mode == 'train': + loss.backward() + optimizer.step() + + # record + sprec1, sprec5 = obtain_accuracy(logits.data, targets.data, topk=(1, 5)) + losses.update(loss.item(), inputs.size(0)) + top1.update (sprec1.item(), inputs.size(0)) + top5.update (sprec5.item(), inputs.size(0)) + # teacher + tprec1, tprec5 = obtain_accuracy(teacher_logits.data, targets.data, topk=(1, 5)) + Ttop1.update (tprec1.item(), inputs.size(0)) + Ttop5.update (tprec5.item(), inputs.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + + if i % print_freq == 0 or (i+1) == len(xloader): + Sstr = ' {:5s} '.format(mode.upper()) + time_string() + ' [{:}][{:03d}/{:03d}]'.format(extra_info, i, len(xloader)) + if scheduler is not None: + Sstr += ' {:}'.format(scheduler.get_min_info()) + Tstr = 'Time {batch_time.val:.2f} ({batch_time.avg:.2f}) Data {data_time.val:.2f} ({data_time.avg:.2f})'.format(batch_time=batch_time, data_time=data_time) + Lstr = 'Loss {loss.val:.3f} ({loss.avg:.3f}) Prec@1 {top1.val:.2f} ({top1.avg:.2f}) Prec@5 {top5.val:.2f} ({top5.avg:.2f})'.format(loss=losses, top1=top1, top5=top5) + Lstr+= ' Teacher : acc@1={:.2f}, acc@5={:.2f}'.format(Ttop1.avg, Ttop5.avg) + Istr = 'Size={:}'.format(list(inputs.size())) + logger.log(Sstr + ' ' + Tstr + ' ' + Lstr + ' ' + Istr) + + logger.log(' **{:5s}** accuracy drop :: @1={:.2f}, @5={:.2f}'.format(mode.upper(), Ttop1.avg - top1.avg, Ttop5.avg - top5.avg)) + logger.log(' **{mode:5s}** Prec@1 {top1.avg:.2f} Prec@5 {top5.avg:.2f} Error@1 {error1:.2f} Error@5 {error5:.2f} Loss:{loss:.3f}'.format(mode=mode.upper(), top1=top1, top5=top5, error1=100-top1.avg, error5=100-top5.avg, loss=losses.avg)) + return losses.avg, top1.avg, top5.avg diff --git a/autodl/procedures/starts.py b/autodl/procedures/starts.py new file mode 100644 index 0000000..438fd07 --- /dev/null +++ b/autodl/procedures/starts.py @@ -0,0 +1,64 @@ +################################################## +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019 # +################################################## +import os, sys, torch, random, PIL, copy, numpy as np +from os import path as osp +from shutil import copyfile + + +def prepare_seed(rand_seed): + random.seed(rand_seed) + np.random.seed(rand_seed) + torch.manual_seed(rand_seed) + torch.cuda.manual_seed(rand_seed) + torch.cuda.manual_seed_all(rand_seed) + + +def prepare_logger(xargs): + args = copy.deepcopy( xargs ) + from autodl.log_utils import Logger + logger = Logger(args.save_dir, args.rand_seed) + logger.log('Main Function with logger : {:}'.format(logger)) + logger.log('Arguments : -------------------------------') + for name, value in args._get_kwargs(): + logger.log('{:16} : {:}'.format(name, value)) + logger.log("Python Version : {:}".format(sys.version.replace('\n', ' '))) + logger.log("Pillow Version : {:}".format(PIL.__version__)) + logger.log("PyTorch Version : {:}".format(torch.__version__)) + logger.log("cuDNN Version : {:}".format(torch.backends.cudnn.version())) + logger.log("CUDA available : {:}".format(torch.cuda.is_available())) + logger.log("CUDA GPU numbers : {:}".format(torch.cuda.device_count())) + logger.log("CUDA_VISIBLE_DEVICES : {:}".format(os.environ['CUDA_VISIBLE_DEVICES'] if 'CUDA_VISIBLE_DEVICES' in os.environ else 'None')) + return logger + + +def get_machine_info(): + info = "Python Version : {:}".format(sys.version.replace('\n', ' ')) + info+= "\nPillow Version : {:}".format(PIL.__version__) + info+= "\nPyTorch Version : {:}".format(torch.__version__) + info+= "\ncuDNN Version : {:}".format(torch.backends.cudnn.version()) + info+= "\nCUDA available : {:}".format(torch.cuda.is_available()) + info+= "\nCUDA GPU numbers : {:}".format(torch.cuda.device_count()) + if 'CUDA_VISIBLE_DEVICES' in os.environ: + info+= "\nCUDA_VISIBLE_DEVICES={:}".format(os.environ['CUDA_VISIBLE_DEVICES']) + else: + info+= "\nDoes not set CUDA_VISIBLE_DEVICES" + return info + + +def save_checkpoint(state, filename, logger): + if osp.isfile(filename): + if hasattr(logger, 'log'): logger.log('Find {:} exist, delete is at first before saving'.format(filename)) + os.remove(filename) + torch.save(state, filename) + assert osp.isfile(filename), 'save filename : {:} failed, which is not found.'.format(filename) + if hasattr(logger, 'log'): logger.log('save checkpoint into {:}'.format(filename)) + return filename + + +def copy_checkpoint(src, dst, logger): + if osp.isfile(dst): + if hasattr(logger, 'log'): logger.log('Find {:} exist, delete is at first before saving'.format(dst)) + os.remove(dst) + copyfile(src, dst) + if hasattr(logger, 'log'): logger.log('copy the file from {:} into {:}'.format(src, dst)) diff --git a/autodl/utils/__init__.py b/autodl/utils/__init__.py new file mode 100644 index 0000000..1cc1647 --- /dev/null +++ b/autodl/utils/__init__.py @@ -0,0 +1,5 @@ +from .evaluation_utils import obtain_accuracy +from .gpu_manager import GPUManager +from .flop_benchmark import get_model_infos, count_parameters_in_MB +from .affine_utils import normalize_points, denormalize_points +from .affine_utils import identity2affine, solve2theta, affine2image diff --git a/autodl/utils/affine_utils.py b/autodl/utils/affine_utils.py new file mode 100644 index 0000000..b122cb4 --- /dev/null +++ b/autodl/utils/affine_utils.py @@ -0,0 +1,125 @@ +# functions for affine transformation +import math, torch +import numpy as np +import torch.nn.functional as F + +def identity2affine(full=False): + if not full: + parameters = torch.zeros((2,3)) + parameters[0, 0] = parameters[1, 1] = 1 + else: + parameters = torch.zeros((3,3)) + parameters[0, 0] = parameters[1, 1] = parameters[2, 2] = 1 + return parameters + +def normalize_L(x, L): + return -1. + 2. * x / (L-1) + +def denormalize_L(x, L): + return (x + 1.0) / 2.0 * (L-1) + +def crop2affine(crop_box, W, H): + assert len(crop_box) == 4, 'Invalid crop-box : {:}'.format(crop_box) + parameters = torch.zeros(3,3) + x1, y1 = normalize_L(crop_box[0], W), normalize_L(crop_box[1], H) + x2, y2 = normalize_L(crop_box[2], W), normalize_L(crop_box[3], H) + parameters[0,0] = (x2-x1)/2 + parameters[0,2] = (x2+x1)/2 + + parameters[1,1] = (y2-y1)/2 + parameters[1,2] = (y2+y1)/2 + parameters[2,2] = 1 + return parameters + +def scale2affine(scalex, scaley): + parameters = torch.zeros(3,3) + parameters[0,0] = scalex + parameters[1,1] = scaley + parameters[2,2] = 1 + return parameters + +def offset2affine(offx, offy): + parameters = torch.zeros(3,3) + parameters[0,0] = parameters[1,1] = parameters[2,2] = 1 + parameters[0,2] = offx + parameters[1,2] = offy + return parameters + +def horizontalmirror2affine(): + parameters = torch.zeros(3,3) + parameters[0,0] = -1 + parameters[1,1] = parameters[2,2] = 1 + return parameters + +# clockwise rotate image = counterclockwise rotate the rectangle +# degree is between [0, 360] +def rotate2affine(degree): + assert degree >= 0 and degree <= 360, 'Invalid degree : {:}'.format(degree) + degree = degree / 180 * math.pi + parameters = torch.zeros(3,3) + parameters[0,0] = math.cos(-degree) + parameters[0,1] = -math.sin(-degree) + parameters[1,0] = math.sin(-degree) + parameters[1,1] = math.cos(-degree) + parameters[2,2] = 1 + return parameters + +# shape is a tuple [H, W] +def normalize_points(shape, points): + assert (isinstance(shape, tuple) or isinstance(shape, list)) and len(shape) == 2, 'invalid shape : {:}'.format(shape) + assert isinstance(points, torch.Tensor) and (points.shape[0] == 2), 'points are wrong : {:}'.format(points.shape) + (H, W), points = shape, points.clone() + points[0, :] = normalize_L(points[0,:], W) + points[1, :] = normalize_L(points[1,:], H) + return points + +# shape is a tuple [H, W] +def normalize_points_batch(shape, points): + assert (isinstance(shape, tuple) or isinstance(shape, list)) and len(shape) == 2, 'invalid shape : {:}'.format(shape) + assert isinstance(points, torch.Tensor) and (points.size(-1) == 2), 'points are wrong : {:}'.format(points.shape) + (H, W), points = shape, points.clone() + x = normalize_L(points[...,0], W) + y = normalize_L(points[...,1], H) + return torch.stack((x,y), dim=-1) + +# shape is a tuple [H, W] +def denormalize_points(shape, points): + assert (isinstance(shape, tuple) or isinstance(shape, list)) and len(shape) == 2, 'invalid shape : {:}'.format(shape) + assert isinstance(points, torch.Tensor) and (points.shape[0] == 2), 'points are wrong : {:}'.format(points.shape) + (H, W), points = shape, points.clone() + points[0, :] = denormalize_L(points[0,:], W) + points[1, :] = denormalize_L(points[1,:], H) + return points + +# shape is a tuple [H, W] +def denormalize_points_batch(shape, points): + assert (isinstance(shape, tuple) or isinstance(shape, list)) and len(shape) == 2, 'invalid shape : {:}'.format(shape) + assert isinstance(points, torch.Tensor) and (points.shape[-1] == 2), 'points are wrong : {:}'.format(points.shape) + (H, W), points = shape, points.clone() + x = denormalize_L(points[...,0], W) + y = denormalize_L(points[...,1], H) + return torch.stack((x,y), dim=-1) + +# make target * theta = source +def solve2theta(source, target): + source, target = source.clone(), target.clone() + oks = source[2, :] == 1 + assert torch.sum(oks).item() >= 3, 'valid points : {:} is short'.format(oks) + if target.size(0) == 2: target = torch.cat((target, oks.unsqueeze(0).float()), dim=0) + source, target = source[:, oks], target[:, oks] + source, target = source.transpose(1,0), target.transpose(1,0) + assert source.size(1) == target.size(1) == 3 + #X, residual, rank, s = np.linalg.lstsq(target.numpy(), source.numpy()) + #theta = torch.Tensor(X.T[:2, :]) + X_, qr = torch.gels(source, target) + theta = X_[:3, :2].transpose(1, 0) + return theta + +# shape = [H,W] +def affine2image(image, theta, shape): + C, H, W = image.size() + theta = theta[:2, :].unsqueeze(0) + grid_size = torch.Size([1, C, shape[0], shape[1]]) + grid = F.affine_grid(theta, grid_size) + affI = F.grid_sample(image.unsqueeze(0), grid, mode='bilinear', padding_mode='border') + return affI.squeeze(0) diff --git a/autodl/utils/evaluation_utils.py b/autodl/utils/evaluation_utils.py new file mode 100644 index 0000000..cf853c8 --- /dev/null +++ b/autodl/utils/evaluation_utils.py @@ -0,0 +1,16 @@ +import torch + +def obtain_accuracy(output, target, topk=(1,)): + """Computes the precision@k for the specified values of k""" + maxk = max(topk) + batch_size = target.size(0) + + _, pred = output.topk(maxk, 1, True, True) + pred = pred.t() + correct = pred.eq(target.view(1, -1).expand_as(pred)) + + res = [] + for k in topk: + correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) + res.append(correct_k.mul_(100.0 / batch_size)) + return res diff --git a/autodl/utils/flop_benchmark.py b/autodl/utils/flop_benchmark.py new file mode 100644 index 0000000..133cf2c --- /dev/null +++ b/autodl/utils/flop_benchmark.py @@ -0,0 +1,181 @@ +import torch +import torch.nn as nn +import numpy as np + + +def count_parameters_in_MB(model): + if isinstance(model, nn.Module): + return np.sum(np.prod(v.size()) for v in model.parameters())/1e6 + else: + return np.sum(np.prod(v.size()) for v in model)/1e6 + + +def get_model_infos(model, shape): + #model = copy.deepcopy( model ) + + model = add_flops_counting_methods(model) + #model = model.cuda() + model.eval() + + #cache_inputs = torch.zeros(*shape).cuda() + #cache_inputs = torch.zeros(*shape) + cache_inputs = torch.rand(*shape) + if next(model.parameters()).is_cuda: cache_inputs = cache_inputs.cuda() + #print_log('In the calculating function : cache input size : {:}'.format(cache_inputs.size()), log) + with torch.no_grad(): + _____ = model(cache_inputs) + FLOPs = compute_average_flops_cost( model ) / 1e6 + Param = count_parameters_in_MB(model) + + if hasattr(model, 'auxiliary_param'): + aux_params = count_parameters_in_MB(model.auxiliary_param()) + print ('The auxiliary params of this model is : {:}'.format(aux_params)) + print ('We remove the auxiliary params from the total params ({:}) when counting'.format(Param)) + Param = Param - aux_params + + #print_log('FLOPs : {:} MB'.format(FLOPs), log) + torch.cuda.empty_cache() + model.apply( remove_hook_function ) + return FLOPs, Param + + +# ---- Public functions +def add_flops_counting_methods( model ): + model.__batch_counter__ = 0 + add_batch_counter_hook_function( model ) + model.apply( add_flops_counter_variable_or_reset ) + model.apply( add_flops_counter_hook_function ) + return model + + + +def compute_average_flops_cost(model): + """ + A method that will be available after add_flops_counting_methods() is called on a desired net object. + Returns current mean flops consumption per image. + """ + batches_count = model.__batch_counter__ + flops_sum = 0 + #or isinstance(module, torch.nn.AvgPool2d) or isinstance(module, torch.nn.MaxPool2d) \ + for module in model.modules(): + if isinstance(module, torch.nn.Conv2d) or isinstance(module, torch.nn.Linear) \ + or isinstance(module, torch.nn.Conv1d) \ + or hasattr(module, 'calculate_flop_self'): + flops_sum += module.__flops__ + return flops_sum / batches_count + + +# ---- Internal functions +def pool_flops_counter_hook(pool_module, inputs, output): + batch_size = inputs[0].size(0) + kernel_size = pool_module.kernel_size + out_C, output_height, output_width = output.shape[1:] + assert out_C == inputs[0].size(1), '{:} vs. {:}'.format(out_C, inputs[0].size()) + + overall_flops = batch_size * out_C * output_height * output_width * kernel_size * kernel_size + pool_module.__flops__ += overall_flops + + +def self_calculate_flops_counter_hook(self_module, inputs, output): + overall_flops = self_module.calculate_flop_self(inputs[0].shape, output.shape) + self_module.__flops__ += overall_flops + + +def fc_flops_counter_hook(fc_module, inputs, output): + batch_size = inputs[0].size(0) + xin, xout = fc_module.in_features, fc_module.out_features + assert xin == inputs[0].size(1) and xout == output.size(1), 'IO=({:}, {:})'.format(xin, xout) + overall_flops = batch_size * xin * xout + if fc_module.bias is not None: + overall_flops += batch_size * xout + fc_module.__flops__ += overall_flops + + +def conv1d_flops_counter_hook(conv_module, inputs, outputs): + batch_size = inputs[0].size(0) + outL = outputs.shape[-1] + [kernel] = conv_module.kernel_size + in_channels = conv_module.in_channels + out_channels = conv_module.out_channels + groups = conv_module.groups + conv_per_position_flops = kernel * in_channels * out_channels / groups + + active_elements_count = batch_size * outL + overall_flops = conv_per_position_flops * active_elements_count + + if conv_module.bias is not None: + overall_flops += out_channels * active_elements_count + conv_module.__flops__ += overall_flops + + +def conv2d_flops_counter_hook(conv_module, inputs, output): + batch_size = inputs[0].size(0) + output_height, output_width = output.shape[2:] + + kernel_height, kernel_width = conv_module.kernel_size + in_channels = conv_module.in_channels + out_channels = conv_module.out_channels + groups = conv_module.groups + conv_per_position_flops = kernel_height * kernel_width * in_channels * out_channels / groups + + active_elements_count = batch_size * output_height * output_width + overall_flops = conv_per_position_flops * active_elements_count + + if conv_module.bias is not None: + overall_flops += out_channels * active_elements_count + conv_module.__flops__ += overall_flops + + +def batch_counter_hook(module, inputs, output): + # Can have multiple inputs, getting the first one + inputs = inputs[0] + batch_size = inputs.shape[0] + module.__batch_counter__ += batch_size + + +def add_batch_counter_hook_function(module): + if not hasattr(module, '__batch_counter_handle__'): + handle = module.register_forward_hook(batch_counter_hook) + module.__batch_counter_handle__ = handle + + +def add_flops_counter_variable_or_reset(module): + if isinstance(module, torch.nn.Conv2d) or isinstance(module, torch.nn.Linear) \ + or isinstance(module, torch.nn.Conv1d) \ + or isinstance(module, torch.nn.AvgPool2d) or isinstance(module, torch.nn.MaxPool2d) \ + or hasattr(module, 'calculate_flop_self'): + module.__flops__ = 0 + + +def add_flops_counter_hook_function(module): + if isinstance(module, torch.nn.Conv2d): + if not hasattr(module, '__flops_handle__'): + handle = module.register_forward_hook(conv2d_flops_counter_hook) + module.__flops_handle__ = handle + elif isinstance(module, torch.nn.Conv1d): + if not hasattr(module, '__flops_handle__'): + handle = module.register_forward_hook(conv1d_flops_counter_hook) + module.__flops_handle__ = handle + elif isinstance(module, torch.nn.Linear): + if not hasattr(module, '__flops_handle__'): + handle = module.register_forward_hook(fc_flops_counter_hook) + module.__flops_handle__ = handle + elif isinstance(module, torch.nn.AvgPool2d) or isinstance(module, torch.nn.MaxPool2d): + if not hasattr(module, '__flops_handle__'): + handle = module.register_forward_hook(pool_flops_counter_hook) + module.__flops_handle__ = handle + elif hasattr(module, 'calculate_flop_self'): # self-defined module + if not hasattr(module, '__flops_handle__'): + handle = module.register_forward_hook(self_calculate_flops_counter_hook) + module.__flops_handle__ = handle + + +def remove_hook_function(module): + hookers = ['__batch_counter_handle__', '__flops_handle__'] + for hooker in hookers: + if hasattr(module, hooker): + handle = getattr(module, hooker) + handle.remove() + keys = ['__flops__', '__batch_counter__', '__flops__'] + hookers + for ckey in keys: + if hasattr(module, ckey): delattr(module, ckey) diff --git a/autodl/utils/gpu_manager.py b/autodl/utils/gpu_manager.py new file mode 100644 index 0000000..520cff4 --- /dev/null +++ b/autodl/utils/gpu_manager.py @@ -0,0 +1,70 @@ +import os + +class GPUManager(): + queries = ('index', 'gpu_name', 'memory.free', 'memory.used', 'memory.total', 'power.draw', 'power.limit') + + def __init__(self): + all_gpus = self.query_gpu(False) + + def get_info(self, ctype): + cmd = 'nvidia-smi --query-gpu={} --format=csv,noheader'.format(ctype) + lines = os.popen(cmd).readlines() + lines = [line.strip('\n') for line in lines] + return lines + + def query_gpu(self, show=True): + num_gpus = len( self.get_info('index') ) + all_gpus = [ {} for i in range(num_gpus) ] + for query in self.queries: + infos = self.get_info(query) + for idx, info in enumerate(infos): + all_gpus[idx][query] = info + + if 'CUDA_VISIBLE_DEVICES' in os.environ: + CUDA_VISIBLE_DEVICES = os.environ['CUDA_VISIBLE_DEVICES'].split(',') + selected_gpus = [] + for idx, CUDA_VISIBLE_DEVICE in enumerate(CUDA_VISIBLE_DEVICES): + find = False + for gpu in all_gpus: + if gpu['index'] == CUDA_VISIBLE_DEVICE: + assert not find, 'Duplicate cuda device index : {}'.format(CUDA_VISIBLE_DEVICE) + find = True + selected_gpus.append( gpu.copy() ) + selected_gpus[-1]['index'] = '{}'.format(idx) + assert find, 'Does not find the device : {}'.format(CUDA_VISIBLE_DEVICE) + all_gpus = selected_gpus + + if show: + allstrings = '' + for gpu in all_gpus: + string = '| ' + for query in self.queries: + if query.find('memory') == 0: xinfo = '{:>9}'.format(gpu[query]) + else: xinfo = gpu[query] + string = string + query + ' : ' + xinfo + ' | ' + allstrings = allstrings + string + '\n' + return allstrings + else: + return all_gpus + + def select_by_memory(self, numbers=1): + all_gpus = self.query_gpu(False) + assert numbers <= len(all_gpus), 'Require {} gpus more than you have'.format(numbers) + alls = [] + for idx, gpu in enumerate(all_gpus): + free_memory = gpu['memory.free'] + free_memory = free_memory.split(' ')[0] + free_memory = int(free_memory) + index = gpu['index'] + alls.append((free_memory, index)) + alls.sort(reverse = True) + alls = [ int(alls[i][1]) for i in range(numbers) ] + return sorted(alls) + +""" +if __name__ == '__main__': + manager = GPUManager() + manager.query_gpu(True) + indexes = manager.select_by_memory(3) + print (indexes) +""" diff --git a/autodl/utils/nas_utils.py b/autodl/utils/nas_utils.py new file mode 100644 index 0000000..1b1a44d --- /dev/null +++ b/autodl/utils/nas_utils.py @@ -0,0 +1,57 @@ +# This file is for experimental usage +import torch, random +import numpy as np +from copy import deepcopy +import torch.nn as nn + +# from utils import obtain_accuracy +from models import CellStructure +from log_utils import time_string + + +def evaluate_one_shot(model, xloader, api, cal_mode, seed=111): + print ('This is an old version of codes to use NAS-Bench-API, and should be modified to align with the new version. Please contact me for more details if you use this function.') + weights = deepcopy(model.state_dict()) + model.train(cal_mode) + with torch.no_grad(): + logits = nn.functional.log_softmax(model.arch_parameters, dim=-1) + archs = CellStructure.gen_all(model.op_names, model.max_nodes, False) + probs, accuracies, gt_accs_10_valid, gt_accs_10_test = [], [], [], [] + loader_iter = iter(xloader) + random.seed(seed) + random.shuffle(archs) + for idx, arch in enumerate(archs): + arch_index = api.query_index_by_arch( arch ) + metrics = api.get_more_info(arch_index, 'cifar10-valid', None, False, False) + gt_accs_10_valid.append( metrics['valid-accuracy'] ) + metrics = api.get_more_info(arch_index, 'cifar10', None, False, False) + gt_accs_10_test.append( metrics['test-accuracy'] ) + select_logits = [] + for i, node_info in enumerate(arch.nodes): + for op, xin in node_info: + node_str = '{:}<-{:}'.format(i+1, xin) + op_index = model.op_names.index(op) + select_logits.append( logits[model.edge2index[node_str], op_index] ) + cur_prob = sum(select_logits).item() + probs.append( cur_prob ) + cor_prob_valid = np.corrcoef(probs, gt_accs_10_valid)[0,1] + cor_prob_test = np.corrcoef(probs, gt_accs_10_test )[0,1] + print ('{:} correlation for probabilities : {:.6f} on CIFAR-10 validation and {:.6f} on CIFAR-10 test'.format(time_string(), cor_prob_valid, cor_prob_test)) + + for idx, arch in enumerate(archs): + model.set_cal_mode('dynamic', arch) + try: + inputs, targets = next(loader_iter) + except: + loader_iter = iter(xloader) + inputs, targets = next(loader_iter) + _, logits = model(inputs.cuda()) + _, preds = torch.max(logits, dim=-1) + correct = (preds == targets.cuda() ).float() + accuracies.append( correct.mean().item() ) + if idx != 0 and (idx % 500 == 0 or idx + 1 == len(archs)): + cor_accs_valid = np.corrcoef(accuracies, gt_accs_10_valid[:idx+1])[0,1] + cor_accs_test = np.corrcoef(accuracies, gt_accs_10_test [:idx+1])[0,1] + print ('{:} {:05d}/{:05d} mode={:5s}, correlation : accs={:.5f} for CIFAR-10 valid, {:.5f} for CIFAR-10 test.'.format(time_string(), idx, len(archs), 'Train' if cal_mode else 'Eval', cor_accs_valid, cor_accs_test)) + model.load_state_dict(weights) + return archs, probs, accuracies diff --git a/autodl/utils/weight_watcher.py b/autodl/utils/weight_watcher.py new file mode 100644 index 0000000..a132c44 --- /dev/null +++ b/autodl/utils/weight_watcher.py @@ -0,0 +1,319 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2020.03 # +##################################################### +# Reformulate the codes in https://github.com/CalculatedContent/WeightWatcher +##################################################### +import numpy as np +from typing import List +import torch.nn as nn +from collections import OrderedDict +from sklearn.decomposition import TruncatedSVD + + +def available_module_types(): + return (nn.Conv2d, nn.Linear) + + +def get_conv2D_Wmats(tensor: np.ndarray) -> List[np.ndarray]: + """ + Extract W slices from a 4 index conv2D tensor of shape: (N,M,i,j) or (M,N,i,j). + Return ij (N x M) matrices + """ + mats = [] + N, M, imax, jmax = tensor.shape + assert N + M >= imax + jmax, 'invalid tensor shape detected: {}x{} (NxM), {}x{} (i,j)'.format(N, M, imax, jmax) + for i in range(imax): + for j in range(jmax): + w = tensor[:, :, i, j] + if N < M: w = w.T + mats.append(w) + return mats + + +def glorot_norm_check(W, N, M, rf_size, lower=0.5, upper=1.5): + """Check if this layer needs Glorot Normalization Fix""" + + kappa = np.sqrt(2 / ((N + M) * rf_size)) + norm = np.linalg.norm(W) + + check1 = norm / np.sqrt(N * M) + check2 = norm / (kappa * np.sqrt(N * M)) + + if (rf_size > 1) and (check2 > lower) and (check2 < upper): + return check2, True + elif (check1 > lower) & (check1 < upper): + return check1, True + else: + if rf_size > 1: return check2, False + else: return check1, False + +def glorot_norm_fix(w, n, m, rf_size): + """Apply Glorot Normalization Fix.""" + kappa = np.sqrt(2 / ((n + m) * rf_size)) + w = w / kappa + return w + + +def analyze_weights(weights, min_size, max_size, alphas, lognorms, spectralnorms, softranks, normalize, glorot_fix): + results = OrderedDict() + count = len(weights) + if count == 0: return results + + for i, weight in enumerate(weights): + M, N = np.min(weight.shape), np.max(weight.shape) + Q = N / M + results[i] = cur_res = OrderedDict(N=N, M=M, Q=Q) + check, checkTF = glorot_norm_check(weight, N, M, count) + cur_res['check'] = check + cur_res['checkTF'] = checkTF + # assume receptive field size is count + if glorot_fix: + weight = glorot_norm_fix(weight, N, M, count) + else: + # probably never needed since we always fix for glorot + weight = weight * np.sqrt(count / 2.0) + + if spectralnorms: # spectralnorm is the max eigenvalues + svd = TruncatedSVD(n_components=1, n_iter=7, random_state=10) + svd.fit(weight) + sv = svd.singular_values_ + sv_max = np.max(sv) + if normalize: + evals = sv * sv / N + else: + evals = sv * sv + lambda0 = evals[0] + cur_res["spectralnorm"] = lambda0 + cur_res["logspectralnorm"] = np.log10(lambda0) + else: + lambda0 = None + + if M < min_size: + summary = "Weight matrix {}/{} ({},{}): Skipping: too small (<{})".format(i + 1, count, M, N, min_size) + cur_res["summary"] = summary + continue + elif max_size > 0 and M > max_size: + summary = "Weight matrix {}/{} ({},{}): Skipping: too big (testing) (>{})".format(i + 1, count, M, N, max_size) + cur_res["summary"] = summary + continue + else: + summary = [] + if alphas: + import powerlaw + svd = TruncatedSVD(n_components=M - 1, n_iter=7, random_state=10) + svd.fit(weight.astype(float)) + sv = svd.singular_values_ + if normalize: evals = sv * sv / N + else: evals = sv * sv + + lambda_max = np.max(evals) + fit = powerlaw.Fit(evals, xmax=lambda_max, verbose=False) + alpha = fit.alpha + cur_res["alpha"] = alpha + D = fit.D + cur_res["D"] = D + cur_res["lambda_min"] = np.min(evals) + cur_res["lambda_max"] = lambda_max + alpha_weighted = alpha * np.log10(lambda_max) + cur_res["alpha_weighted"] = alpha_weighted + tolerance = lambda_max * M * np.finfo(np.max(sv)).eps + cur_res["rank_loss"] = np.count_nonzero(sv > tolerance, axis=-1) + + logpnorm = np.log10(np.sum([ev ** alpha for ev in evals])) + cur_res["logpnorm"] = logpnorm + + summary.append( + "Weight matrix {}/{} ({},{}): Alpha: {}, Alpha Weighted: {}, D: {}, pNorm {}".format(i + 1, count, M, N, alpha, + alpha_weighted, D, + logpnorm)) + + if lognorms: + norm = np.linalg.norm(weight) # Frobenius Norm + cur_res["norm"] = norm + lognorm = np.log10(norm) + cur_res["lognorm"] = lognorm + + X = np.dot(weight.T, weight) + if normalize: X = X / N + normX = np.linalg.norm(X) # Frobenius Norm + cur_res["normX"] = normX + lognormX = np.log10(normX) + cur_res["lognormX"] = lognormX + + summary.append( + "Weight matrix {}/{} ({},{}): LogNorm: {} ; LogNormX: {}".format(i + 1, count, M, N, lognorm, lognormX)) + + if softranks: + softrank = norm ** 2 / sv_max ** 2 + softranklog = np.log10(softrank) + softranklogratio = lognorm / np.log10(sv_max) + cur_res["softrank"] = softrank + cur_res["softranklog"] = softranklog + cur_res["softranklogratio"] = softranklogratio + summary += "{}. Softrank: {}. Softrank log: {}. Softrank log ratio: {}".format(summary, softrank, softranklog, + softranklogratio) + cur_res["summary"] = "\n".join(summary) + return results + + +def compute_details(results): + """ + Return a pandas data frame. + """ + final_summary = OrderedDict() + + metrics = { + # key in "results" : pretty print name + "check": "Check", + "checkTF": "CheckTF", + "norm": "Norm", + "lognorm": "LogNorm", + "normX": "Norm X", + "lognormX": "LogNorm X", + "alpha": "Alpha", + "alpha_weighted": "Alpha Weighted", + "spectralnorm": "Spectral Norm", + "logspectralnorm": "Log Spectral Norm", + "softrank": "Softrank", + "softranklog": "Softrank Log", + "softranklogratio": "Softrank Log Ratio", + "sigma_mp": "Marchenko-Pastur (MP) fit sigma", + "numofSpikes": "Number of spikes per MP fit", + "ratio_numofSpikes": "aka, percent_mass, Number of spikes / total number of evals", + "softrank_mp": "Softrank for MP fit", + "logpnorm": "alpha pNorm" + } + + metrics_stats = [] + for metric in metrics: + metrics_stats.append("{}_min".format(metric)) + metrics_stats.append("{}_max".format(metric)) + metrics_stats.append("{}_avg".format(metric)) + + metrics_stats.append("{}_compound_min".format(metric)) + metrics_stats.append("{}_compound_max".format(metric)) + metrics_stats.append("{}_compound_avg".format(metric)) + + columns = ["layer_id", "layer_type", "N", "M", "layer_count", "slice", + "slice_count", "level", "comment"] + [*metrics] + metrics_stats + + metrics_values = {} + metrics_values_compound = {} + + for metric in metrics: + metrics_values[metric] = [] + metrics_values_compound[metric] = [] + + layer_count = 0 + for layer_id, result in results.items(): + layer_count += 1 + + layer_type = np.NAN + if "layer_type" in result: + layer_type = str(result["layer_type"]).replace("LAYER_TYPE.", "") + + compounds = {} # temp var + for metric in metrics: + compounds[metric] = [] + + slice_count, Ntotal, Mtotal = 0, 0, 0 + for slice_id, summary in result.items(): + if not str(slice_id).isdigit(): + continue + slice_count += 1 + + N = np.NAN + if "N" in summary: + N = summary["N"] + Ntotal += N + + M = np.NAN + if "M" in summary: + M = summary["M"] + Mtotal += M + + data = {"layer_id": layer_id, "layer_type": layer_type, "N": N, "M": M, "slice": slice_id, "level": "SLICE", + "comment": "Slice level"} + for metric in metrics: + if metric in summary: + value = summary[metric] + if value is not None: + metrics_values[metric].append(value) + compounds[metric].append(value) + data[metric] = value + + data = {"layer_id": layer_id, "layer_type": layer_type, "N": Ntotal, "M": Mtotal, "slice_count": slice_count, + "level": "LAYER", "comment": "Layer level"} + # Compute the compound value over the slices + for metric, value in compounds.items(): + count = len(value) + if count == 0: + continue + + compound = np.mean(value) + metrics_values_compound[metric].append(compound) + data[metric] = compound + + data = {"layer_count": layer_count, "level": "NETWORK", "comment": "Network Level"} + for metric, metric_name in metrics.items(): + if metric not in metrics_values or len(metrics_values[metric]) == 0: + continue + + values = metrics_values[metric] + minimum = min(values) + maximum = max(values) + avg = np.mean(values) + final_summary[metric] = avg + # print("{}: min: {}, max: {}, avg: {}".format(metric_name, minimum, maximum, avg)) + data["{}_min".format(metric)] = minimum + data["{}_max".format(metric)] = maximum + data["{}_avg".format(metric)] = avg + + values = metrics_values_compound[metric] + minimum = min(values) + maximum = max(values) + avg = np.mean(values) + final_summary["{}_compound".format(metric)] = avg + # print("{} compound: min: {}, max: {}, avg: {}".format(metric_name, minimum, maximum, avg)) + data["{}_compound_min".format(metric)] = minimum + data["{}_compound_max".format(metric)] = maximum + data["{}_compound_avg".format(metric)] = avg + + return final_summary + + +def analyze(model: nn.Module, min_size=50, max_size=0, + alphas: bool = False, lognorms: bool = True, spectralnorms: bool = False, + softranks: bool = False, normalize: bool = False, glorot_fix: bool = False): + """ + Analyze the weight matrices of a model. + :param model: A PyTorch model + :param min_size: The minimum weight matrix size to analyze. + :param max_size: The maximum weight matrix size to analyze (0 = no limit). + :param alphas: Compute the power laws (alpha) of the weight matrices. + Time consuming so disabled by default (use lognorm if you want speed) + :param lognorms: Compute the log norms of the weight matrices. + :param spectralnorms: Compute the spectral norm (max eigenvalue) of the weight matrices. + :param softranks: Compute the soft norm (i.e. StableRank) of the weight matrices. + :param normalize: Normalize or not. + :param glorot_fix: + :return: (a dict of all layers' results, a dict of the summarized info) + """ + names, modules = [], [] + for name, module in model.named_modules(): + if isinstance(module, available_module_types()): + names.append(name) + modules.append(module) + # print('There are {:} layers to be analyzed in this model.'.format(len(modules))) + all_results = OrderedDict() + for index, module in enumerate(modules): + if isinstance(module, nn.Linear): + weights = [module.weight.cpu().detach().numpy()] + else: + weights = get_conv2D_Wmats(module.weight.cpu().detach().numpy()) + results = analyze_weights(weights, min_size, max_size, alphas, lognorms, spectralnorms, softranks, normalize, glorot_fix) + results['id'] = index + results['type'] = type(module) + all_results[index] = results + summary = compute_details(all_results) + return all_results, summary \ No newline at end of file diff --git a/config_utils/cifar-split.txt b/config_utils/cifar-split.txt deleted file mode 100644 index 56b7665..0000000 --- a/config_utils/cifar-split.txt +++ /dev/null @@ -1,4 +0,0 @@ -{ - "train" : ["int" , ["0", "5", "7", "11", "13", "15", "16", "17", "20", "24", "26", "28", "30", "31", "32", "34", "36", "37", "39", "40", "43", "46", "48", "49", "50", "52", "53", "55", "56", "58", "60", "66", "68", "69", "74", "75", "77", "78", "79", "81", "86", "88", "90", "93", "94", "96", "97", "100", "101", "103", "104", "106", "107", "109", "111", "112", "113", "114", "115", "117", "118", "120", "122", "123", "124", "125", "126", "128", "129", "131", "132", "134", "135", "136", "137", "139", "140", "141", "142", "144", "147", "148", "151", "152", "155", "156", "158", "161", "162", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", "178", "179", "185", "188", "189", "192", "193", "195", "196", "197", "203", "204", "205", "206", "207", "209", "210", "211", "212", "213", "216", "217", "225", "226", "227", "228", "229", "231", "233", "241", "243", "245", "247", "250", "251", "252", "254", "255", "256", "257", "259", "262", "263", "268", "269", "271", "272", "273", "275", "276", "278", "280", "282", "284", "287", "288", "291", "295", "296", "297", "300", "301", "302", "303", "305", "312", "315", "317", "318", "319", "322", "323", "327", "328", "329", "332", "333", "335", "336", "338", "340", "341", "343", "347", "351", "355", "361", "364", "367", "369", "370", "371", "372", "375", "376", "380", "381", "386", "387", "388", "389", "397", "398", "399", "400", "402", "403", "405", "406", "408", "412", "414", "415", "422", "424", "425", "430", "431", "432", "433", "434", "435", "438", "439", "440", "443", "444", "445", "451", "452", "453", "454", "456", "457", "461", "465", "466", "469", "471", "476", "478", "483", "484", "487", "493", "497", "498", "500", "503", "504", "506", "507", "508", "510", "513", "514", "516", "522", "525", "527", "529", "531", "532", "533", "535", "539", "544", "545", "546", "547", "548", "549", "551", "553", "554", "557", "564", "565", "567", "568", "572", "573", "578", "579", "582", "584", "585", "589", "590", "591", "595", "596", "597", "598", "600", "601", "602", "604", "605", "608", "612", "615", "619", "620", "621", "624", "625", "626", "627", "629", "631", "634", "637", "639", "641", "643", "645", "649", "650", "652", "653", "655", "666", "668", "670", "671", "673", "674", "676", "677", "679", "680", "683", "686", "687", "688", "691", "694", "695", "696", "700", "705", "707", "710", "716", "717", "721", "722", "724", "727", "729", "731", "732", "734", "735", "737", "738", "739", "741", "742", "748", "751", "752", "756", "760", "761", "765", "768", "771", "774", "775", "777", "781", "783", "784", "785", "787", "789", "790", "791", "793", "794", "797", "798", "799", "800", "803", "807", "809", "811", "812", "815", "816", "817", "819", "820", "821", "822", "823", "825", "827", "828", "831", "832", "833", "837", "838", "841", "842", "846", "853", "854", "855", "857", "859", "861", "864", "868", "869", "870", "871", "872", "873", "876", "881", "885", "887", "889", "896", "897", "899", "900", "901", "902", "903", "905", "906", "907", "909", "910", "911", "912", "913", "914", "918", "919", "922", "923", "925", "927", "934", "935", "937", "944", "945", "946", "948", "951", "953", "954", "957", "958", "959", "960", "961", "964", "965", "966", "967", "968", "970", "972", "973", "975", "978", "979", "980", "981", "986", "987", "988", "990", "991", "992", "993", "994", "995", "996", "997", "1005", "1006", "1008", "1009", "1012", "1014", "1015", "1018", "1021", "1022", "1023", "1024", "1029", "1030", "1032", "1035", "1037", "1038", "1042", "1043", "1044", "1047", "1049", "1052", "1053", "1055", "1056", "1057", "1062", "1063", "1065", "1066", "1067", "1068", "1071", "1074", "1076", "1077", "1079", "1080", "1081", "1084", "1085", "1087", "1091", "1094", "1096", "1100", "1101", "1102", "1103", "1106", "1107", "1108", "1109", "1110", "1111", "1112", "1113", "1115", "1116", "1117", "1118", "1119", "1123", "1129", "1132", "1135", "1137", "1138", "1139", "1140", "1142", "1143", "1144", "1150", "1151", "1154", "1155", "1156", "1157", "1158", "1160", "1162", "1165", "1166", "1171", "1175", "1177", "1179", "1180", "1181", "1184", "1185", "1186", "1187", "1193", "1194", "1199", "1202", "1208", "1213", "1214", "1217", "1219", "1220", "1223", "1225", "1226", "1227", "1228", "1229", "1231", "1233", "1235", "1236", "1237", "1238", "1239", "1242", "1243", "1244", "1245", "1246", "1249", "1251", "1252", "1256", "1257", "1260", "1264", "1266", "1269", "1272", "1274", "1276", "1277", "1278", "1279", "1280", "1282", "1283", "1285", "1286", "1287", "1288", "1289", "1291", "1292", "1294", "1295", "1297", "1298", "1300", "1302", "1304", "1305", "1306", "1308", "1310", "1311", "1313", "1316", "1317", "1318", "1319", "1320", "1321", "1322", "1324", "1325", "1327", "1329", "1331", "1334", "1335", "1338", "1339", "1341", "1342", "1348", "1351", "1352", "1354", "1355", "1357", "1363", "1367", "1369", "1372", "1375", "1376", "1378", "1380", "1381", "1383", "1386", "1388", "1389", "1390", "1391", "1392", "1393", "1395", "1396", "1401", "1403", "1406", "1410", "1414", "1415", "1419", "1420", "1421", "1422", "1425", "1426", "1427", "1429", "1432", "1434", "1439", "1444", "1445", "1446", "1448", "1450", "1454", "1456", "1458", "1460", "1461", "1463", "1467", "1469", "1472", "1475", "1479", "1482", "1483", "1484", "1486", "1487", "1490", "1492", "1493", "1497", "1503", "1504", "1506", "1507", "1510", "1511", "1512", "1513", "1516", "1518", "1520", "1522", "1523", "1524", "1525", "1526", "1527", "1531", "1532", "1534", "1536", "1538", "1539", "1541", "1544", "1545", "1546", "1547", "1548", "1550", "1551", "1552", "1553", "1555", "1556", "1559", "1561", "1563", "1564", "1566", "1570", "1579", "1580", "1581", "1585", "1586", "1587", "1589", "1590", "1591", "1593", "1594", "1595", "1604", "1605", "1608", "1609", "1612", "1614", "1620", "1622", "1623", "1625", "1626", "1628", "1632", "1634", "1635", "1636", "1637", "1638", "1639", "1640", "1641", "1642", "1651", "1652", "1654", "1656", "1660", "1661", "1663", "1664", "1665", "1668", "1669", "1670", "1671", "1673", "1674", "1676", "1677", "1684", "1685", "1686", "1687", "1688", "1690", "1691", "1695", "1697", "1699", "1700", "1701", "1704", "1705", "1709", "1710", "1711", "1712", "1713", "1715", "1717", "1718", "1720", "1721", "1722", "1723", "1724", "1733", "1734", "1739", "1740", "1741", "1742", "1744", "1746", "1748", "1749", "1750", "1752", "1754", "1756", "1757", "1759", "1760", "1761", "1763", "1765", "1766", "1767", "1768", "1769", "1770", "1771", "1772", "1775", "1776", "1777", "1778", "1784", "1788", "1790", "1791", "1792", "1798", "1803", "1805", "1806", "1810", "1812", "1815", "1817", "1819", "1820", "1826", "1829", "1831", "1833", "1834", "1835", "1837", "1840", "1841", "1844", "1845", "1846", "1849", "1850", "1851", "1852", "1853", "1855", "1862", "1864", "1865", "1869", "1871", "1872", "1874", "1876", "1880", "1882", "1883", "1885", "1887", "1888", "1889", "1891", "1892", "1893", "1895", "1896", "1897", "1899", "1900", "1901", "1904", "1905", "1906", "1908", "1912", "1914", "1915", "1916", "1920", "1923", "1924", "1925", "1926", "1932", "1934", "1935", "1936", "1937", "1939", "1943", "1945", "1946", "1947", "1949", "1951", "1955", "1956", "1962", "1966", "1969", "1970", "1971", "1972", "1973", "1974", "1975", "1979", "1980", "1981", "1983", "1985", "1986", "1990", "1991", "1992", "1997", "1998", "2001", "2002", "2003", "2005", "2006", "2008", "2009", "2010", "2015", "2016", "2018", "2019", "2020", "2021", "2022", "2023", "2028", "2029", "2030", "2031", "2033", "2037", "2040", "2042", "2047", "2049", "2051", "2053", "2055", "2056", "2061", "2062", "2065", "2066", "2067", "2068", "2069", "2070", "2071", "2072", "2074", "2076", "2079", "2081", "2083", "2084", "2085", "2086", "2088", "2091", "2092", "2093", "2096", "2098", "2099", "2100", "2102", "2103", "2104", "2105", "2106", "2107", "2110", "2111", "2113", "2114", "2119", "2122", "2125", "2126", "2127", "2128", "2131", "2135", "2138", "2140", "2142", "2143", "2145", "2147", "2149", "2150", "2151", "2152", "2153", "2156", "2157", "2159", "2160", "2161", "2163", "2168", "2170", "2173", "2174", "2175", "2176", "2179", "2180", "2181", "2182", "2183", "2187", "2188", "2189", "2193", "2194", "2196", "2198", "2200", "2201", "2204", "2205", "2206", "2207", "2211", "2213", "2214", "2215", "2217", "2218", "2226", "2227", "2229", "2230", "2233", "2234", "2235", "2240", "2241", "2242", "2245", "2248", "2249", "2250", "2251", "2252", "2254", "2255", "2257", "2258", "2259", "2260", "2266", "2267", "2269", "2271", "2272", "2273", "2274", "2275", "2276", "2284", "2286", "2289", "2291", "2294", "2295", "2299", "2301", "2302", "2303", "2304", "2309", "2312", "2313", "2315", "2316", "2318", "2319", "2321", "2322", "2323", "2324", "2325", "2327", "2329", "2330", "2333", "2338", "2340", "2343", "2344", "2346", "2347", "2349", "2350", "2351", "2352", "2353", "2355", "2358", "2359", "2361", "2363", "2365", "2368", "2370", "2372", "2373", "2376", "2382", "2383", "2386", "2389", "2390", "2392", "2398", "2399", "2401", "2411", "2413", "2414", "2416", "2418", "2422", "2424", "2429", "2430", "2432", "2434", "2439", "2440", "2441", "2442", "2445", "2447", "2448", "2449", "2450", "2451", "2453", "2457", "2458", "2459", "2461", "2465", "2466", "2469", "2470", "2472", "2473", "2474", "2476", "2478", "2481", "2483", "2484", "2485", "2486", "2488", "2489", "2493", "2496", "2498", "2499", "2501", "2502", "2504", "2505", "2506", "2508", "2514", "2515", "2516", "2518", "2520", "2521", "2524", "2525", "2528", "2529", "2530", "2531", "2532", "2537", "2539", "2540", "2542", "2543", "2544", "2545", "2546", "2548", "2549", "2551", "2554", "2556", "2563", "2564", "2566", "2567", "2568", "2569", "2570", "2573", "2577", "2579", "2580", "2581", "2584", "2585", "2586", "2587", "2588", "2589", "2590", "2592", "2593", "2594", "2596", "2597", "2599", "2602", "2603", "2604", "2605", "2607", "2610", "2611", "2612", "2614", "2615", "2616", "2617", "2619", "2621", "2622", "2624", "2625", "2627", "2628", "2629", "2630", "2634", "2636", "2637", "2640", "2641", "2642", "2645", "2646", "2649", "2651", "2652", "2653", "2655", "2656", "2657", "2659", "2661", "2663", "2665", "2666", "2668", "2670", "2671", "2674", "2676", "2677", "2678", "2679", "2680", "2681", "2682", "2684", "2685", "2686", "2687", "2688", "2690", "2691", "2693", "2697", "2698", "2700", "2706", "2707", "2708", "2710", "2711", "2713", "2714", "2715", "2716", "2719", "2720", "2721", "2731", "2734", "2735", "2736", "2739", "2740", "2743", "2744", "2746", "2748", "2752", "2753", "2756", "2757", "2759", "2760", "2761", "2762", "2763", "2764", "2765", "2770", "2771", "2774", "2775", "2776", "2779", "2781", "2782", "2785", "2787", "2790", "2792", "2793", "2794", "2795", "2796", "2798", "2802", "2803", "2806", "2808", "2809", "2810", "2811", "2815", "2822", "2824", "2826", "2827", "2828", "2829", "2830", "2834", "2835", "2836", "2837", "2839", "2842", "2843", "2844", "2849", "2850", "2851", "2853", "2854", "2856", "2857", "2866", "2867", "2868", "2872", "2874", "2875", "2876", "2879", "2880", "2886", "2887", "2892", "2894", "2895", "2896", "2898", "2900", "2901", "2902", "2905", "2906", "2908", "2909", "2910", "2913", "2914", "2915", "2916", "2917", "2919", "2923", "2924", "2925", "2927", "2929", "2930", "2934", "2935", "2938", "2939", "2940", "2942", "2943", "2945", "2946", "2947", "2948", "2950", "2952", "2957", "2959", "2962", "2965", "2967", "2968", "2971", "2974", "2975", "2976", "2977", "2978", "2985", "2988", "2989", "2990", "2991", "2992", "2998", "3002", "3003", "3004", "3005", "3006", "3007", "3008", "3009", "3011", "3012", "3013", "3014", "3015", "3016", "3017", "3019", "3021", "3022", "3028", "3033", "3036", "3039", "3045", "3046", "3047", "3050", "3051", "3057", "3058", "3059", "3060", "3061", "3065", "3066", "3067", "3068", "3070", "3072", "3074", "3078", "3080", "3085", "3087", "3088", "3089", "3090", "3091", "3096", "3100", "3101", "3103", "3110", "3111", "3112", "3114", "3115", "3117", "3119", "3121", "3122", "3123", "3124", "3126", "3127", "3130", "3133", "3137", "3139", "3140", "3141", "3143", "3145", "3146", "3150", "3151", "3154", "3157", "3159", "3160", "3163", "3165", "3166", "3167", "3169", "3171", "3174", "3175", "3176", "3178", "3179", "3180", "3184", "3185", "3186", "3188", "3190", "3193", "3194", "3197", "3198", "3202", "3203", "3206", "3208", "3209", "3211", "3212", "3213", "3215", "3217", "3220", "3222", "3225", "3228", "3229", "3230", "3231", "3232", "3234", "3236", "3241", "3243", "3248", "3249", "3250", "3252", "3261", "3263", "3264", "3265", "3267", "3269", "3270", "3271", "3273", "3274", "3276", "3280", "3281", "3282", "3283", "3284", "3285", "3287", "3288", "3289", "3291", "3293", "3294", "3295", "3297", "3298", "3299", "3300", "3301", "3308", "3310", "3311", "3312", "3315", "3316", "3318", "3319", "3320", "3331", "3332", "3333", "3335", "3338", "3339", "3340", "3341", "3342", "3343", "3344", "3345", "3349", "3352", "3355", "3356", "3358", "3359", "3362", "3365", "3366", "3367", "3368", "3370", "3373", "3375", "3376", "3378", "3379", "3384", "3386", "3388", "3390", "3391", "3392", "3396", "3398", "3400", "3402", "3404", "3405", "3406", "3407", "3408", "3410", "3412", "3416", "3420", "3421", "3422", "3423", "3425", "3426", "3427", "3428", "3430", "3431", "3432", "3434", "3435", "3436", "3440", "3442", "3444", "3445", "3447", "3448", "3449", "3451", "3453", "3455", "3457", "3458", "3462", "3463", "3466", "3468", "3472", "3475", "3476", "3479", "3480", "3482", "3483", "3484", "3485", "3488", "3490", "3491", "3492", "3493", "3494", "3496", "3500", "3504", "3509", "3512", "3513", "3515", "3517", "3518", "3522", "3524", "3527", "3528", "3529", "3530", "3534", "3536", "3537", "3539", "3541", "3544", "3546", "3547", "3550", "3551", "3552", "3553", "3554", "3555", "3558", "3563", "3564", "3567", "3569", "3570", "3572", "3577", "3578", "3579", "3580", "3583", "3586", "3592", "3593", "3596", "3597", "3598", "3600", "3601", "3602", "3605", "3606", "3608", "3610", "3613", "3616", "3617", "3618", "3621", "3622", "3624", "3629", "3632", "3634", "3635", "3639", "3641", "3642", "3643", "3645", "3648", "3650", "3658", "3659", "3661", "3664", "3666", "3667", "3671", "3672", "3673", "3674", "3676", "3677", "3678", "3679", "3681", "3686", "3687", "3689", "3690", "3692", "3693", "3696", "3697", "3700", "3701", "3703", "3708", "3709", "3710", "3711", "3712", "3714", "3717", "3718", "3720", "3721", "3723", "3724", "3726", "3728", "3729", "3731", "3732", "3735", "3736", "3738", "3740", "3742", "3744", "3745", "3747", "3748", "3750", "3751", "3756", "3760", "3761", "3764", "3769", "3771", "3774", "3777", "3779", "3780", "3784", "3788", "3795", "3799", "3803", "3804", "3807", "3808", "3810", "3811", "3813", "3814", "3817", "3823", "3826", "3827", "3828", "3829", "3830", "3834", "3835", "3837", "3839", "3842", "3844", "3845", "3846", "3851", "3852", "3853", "3854", "3856", "3859", "3862", "3865", "3866", "3867", "3868", "3869", "3870", "3872", "3874", "3875", "3876", "3877", "3881", "3882", "3883", "3885", "3888", "3890", "3891", "3892", "3893", "3894", "3895", "3896", "3898", "3900", "3901", "3902", "3903", "3905", "3908", "3911", "3916", "3917", "3918", "3919", "3922", "3924", "3925", "3926", "3927", "3929", "3930", "3931", "3932", "3934", "3936", "3937", "3943", "3944", "3945", "3946", "3947", "3950", "3952", "3954", "3955", "3956", "3957", "3959", "3960", "3961", "3963", "3964", "3968", "3971", "3973", "3978", "3980", "3981", "3982", "3983", "3984", "3985", "3986", "3987", "3991", "3992", "3993", "3994", "3997", "3999", "4000", "4002", "4003", "4006", "4007", "4008", "4009", "4010", "4015", "4016", "4018", "4020", "4021", "4027", "4032", "4033", "4035", "4036", "4038", "4040", "4041", "4045", "4047", "4052", "4053", "4054", "4057", "4058", "4059", "4061", "4062", "4065", "4069", "4071", "4072", "4073", "4074", "4076", "4079", "4080", "4085", "4086", "4088", "4089", "4091", "4093", "4095", "4096", "4097", "4098", "4100", "4101", "4102", "4103", "4104", "4109", "4112", "4114", "4117", "4119", "4122", "4125", "4127", "4128", "4129", "4133", "4135", "4137", "4138", "4139", "4141", "4142", "4147", "4148", "4151", "4152", "4156", "4157", "4158", "4159", "4160", "4162", "4166", "4169", "4170", "4171", "4176", "4179", "4180", "4181", "4182", "4188", "4191", "4194", "4195", "4199", "4200", "4201", "4202", "4203", "4205", "4207", "4215", "4216", "4219", "4225", "4226", "4228", "4229", "4230", "4233", "4236", "4244", "4245", "4246", "4247", "4248", "4249", "4250", "4256", "4257", "4258", "4260", "4265", "4267", "4270", "4275", "4277", "4279", "4281", "4282", "4283", "4284", "4289", "4291", "4293", "4295", "4297", "4298", "4299", "4302", "4303", "4304", "4305", "4306", "4307", "4309", "4310", "4312", "4314", "4315", "4316", "4318", "4319", "4323", "4326", "4328", "4331", "4333", "4335", "4336", "4338", "4340", "4341", "4344", "4348", "4349", "4350", "4352", "4353", "4356", "4357", "4358", "4360", "4361", "4362", "4365", "4369", "4370", "4372", "4374", "4375", "4376", "4377", "4378", "4382", "4388", "4389", "4391", "4392", "4393", "4399", "4405", "4406", "4408", "4409", "4410", "4411", "4412", "4413", "4417", "4422", "4423", "4426", "4428", "4432", "4433", "4434", "4435", "4437", "4438", "4439", "4441", "4444", "4445", "4446", "4450", "4451", "4452", "4453", "4454", "4455", "4456", "4457", "4459", "4461", "4464", "4466", "4467", "4471", "4473", "4474", "4475", "4476", "4477", "4478", "4481", "4484", "4485", "4488", "4490", "4496", "4497", "4502", "4503", "4506", "4509", "4510", "4511", "4512", "4513", "4514", "4517", "4521", "4524", "4526", "4527", "4528", "4532", "4534", "4536", "4537", "4538", "4540", "4541", "4546", "4547", "4548", "4549", "4551", "4552", "4554", "4555", "4557", "4558", "4560", "4561", "4562", "4563", "4564", "4565", "4567", "4568", "4573", "4575", "4578", "4580", "4581", "4584", "4589", "4590", "4596", "4597", "4600", "4602", "4603", "4606", "4607", "4608", "4609", "4611", "4613", "4618", "4619", "4620", "4621", "4623", "4624", "4627", "4628", "4629", "4634", "4643", "4644", "4649", "4652", "4653", "4654", "4656", "4661", "4663", "4666", "4667", "4668", "4669", "4670", "4673", "4675", "4680", "4687", "4691", "4692", "4693", "4694", "4695", "4697", "4700", "4701", "4702", "4703", "4704", "4705", "4707", "4708", "4710", "4711", "4713", "4714", "4715", "4716", "4717", "4718", "4719", "4722", "4724", "4726", "4727", "4728", "4729", "4732", "4736", "4739", "4740", "4741", "4742", "4743", "4744", "4745", "4748", "4749", "4750", "4753", "4756", "4757", "4760", "4763", "4766", "4767", "4769", "4770", "4771", "4776", "4777", "4781", "4786", "4788", "4791", "4793", "4794", "4798", "4799", "4800", "4801", "4802", "4803", "4809", "4810", "4811", "4812", "4814", "4816", "4818", "4819", "4820", "4823", "4824", "4826", "4827", "4828", "4830", "4833", "4835", "4839", "4841", "4844", "4845", "4847", "4848", "4849", "4854", "4859", "4862", "4863", "4866", "4871", "4873", "4875", "4876", "4877", "4879", "4880", "4885", "4886", "4889", "4891", "4892", "4894", "4895", "4897", "4898", "4899", "4900", "4902", "4903", "4906", "4907", "4908", "4909", "4910", "4912", "4915", "4917", "4919", "4921", "4922", "4923", "4926", "4932", "4939", "4941", "4942", "4944", "4946", "4948", "4950", "4952", "4955", "4956", "4960", "4961", "4968", "4969", "4970", "4972", "4975", "4976", "4977", "4978", "4980", "4982", "4983", "4984", "4986", "4987", "4989", "4990", "4991", "4996", "4997", "4998", "4999", "5001", "5002", "5003", "5005", "5007", "5010", "5013", "5014", "5015", "5016", "5018", "5024", "5027", "5030", "5031", "5032", "5036", "5038", "5039", "5040", "5042", "5046", "5047", "5048", "5049", "5050", "5051", "5052", "5053", "5054", "5055", "5056", "5058", "5059", "5060", "5062", "5063", "5065", "5067", "5074", "5075", "5077", "5078", "5080", "5082", "5084", "5085", "5086", "5087", "5093", "5094", "5095", "5097", "5099", "5101", "5102", "5103", "5104", "5106", "5107", "5108", "5110", "5112", "5113", "5115", "5117", "5118", "5119", "5123", "5124", "5126", "5128", "5130", "5131", "5132", "5133", "5134", "5135", "5136", "5140", "5142", "5143", "5145", "5147", "5148", "5150", "5154", "5158", "5162", "5163", "5164", "5165", "5167", "5168", "5169", "5170", "5172", "5174", "5175", "5176", "5177", "5179", "5180", "5182", "5184", "5186", "5187", "5190", "5192", "5193", "5194", "5195", "5198", "5201", "5202", "5204", "5205", "5207", "5208", "5209", "5210", "5212", "5213", "5215", "5217", "5220", "5226", "5227", "5228", "5229", "5230", "5231", "5232", "5235", "5236", "5239", "5241", "5243", "5245", "5246", "5247", "5248", "5249", "5251", "5253", "5255", "5256", "5257", "5259", "5260", "5261", "5262", "5265", "5266", "5267", "5268", "5269", "5270", "5271", "5273", "5274", "5275", "5279", "5280", "5281", "5282", "5283", "5285", "5287", "5290", "5293", "5295", "5296", "5299", "5300", "5301", "5303", "5306", "5309", "5310", "5311", "5312", "5313", "5315", "5317", "5319", "5322", "5323", "5325", "5326", "5327", "5330", "5331", "5332", "5334", "5335", "5337", "5338", "5339", "5346", "5347", "5350", "5351", "5352", "5355", "5359", "5360", "5364", "5365", "5366", "5368", "5370", "5371", "5373", "5376", "5377", "5378", "5385", "5389", "5390", "5391", "5396", "5397", "5400", "5402", "5404", "5405", "5406", "5407", "5409", "5415", "5419", "5421", "5424", "5425", "5429", "5434", "5435", "5437", "5439", "5440", "5441", "5442", "5444", "5445", "5446", "5447", "5448", "5450", "5451", "5453", "5456", "5467", "5471", "5474", "5475", "5476", "5477", "5478", "5479", "5482", "5486", "5487", "5489", "5493", "5494", "5497", "5500", "5501", "5502", "5503", "5505", "5506", "5507", "5512", "5513", "5514", "5515", "5516", "5518", "5519", "5520", "5521", "5522", "5525", "5527", "5528", "5529", "5532", "5533", "5534", "5536", "5537", "5539", "5545", "5546", "5547", "5549", "5551", "5553", "5554", "5558", "5559", "5561", "5565", "5566", "5567", "5568", "5569", "5572", "5575", "5578", "5582", "5586", "5588", "5589", "5590", "5596", "5601", "5606", "5607", "5609", "5611", "5614", "5615", "5616", "5617", "5618", "5620", "5623", "5624", "5625", "5626", "5627", "5628", "5634", "5635", "5638", "5639", "5640", "5644", "5645", "5647", "5648", "5649", "5653", "5657", "5659", "5663", "5667", "5676", "5678", "5679", "5683", "5686", "5688", "5691", "5695", "5697", "5698", "5699", "5700", "5701", "5703", "5704", "5705", "5706", "5709", "5711", "5713", "5716", "5717", "5719", "5721", "5722", "5723", "5726", "5731", "5732", "5733", "5734", "5739", "5741", "5742", "5743", "5744", "5745", "5746", "5747", "5751", "5752", "5754", "5755", "5761", "5763", "5764", "5766", "5768", "5769", "5770", "5771", "5772", "5773", "5775", "5776", "5780", "5781", "5782", "5784", "5785", "5788", "5789", "5792", "5794", "5795", "5796", "5798", "5799", "5804", "5812", "5813", "5814", "5815", "5816", "5818", "5819", "5821", "5822", "5824", "5826", "5827", "5830", "5834", "5835", "5840", "5842", "5844", "5846", "5847", "5849", "5850", "5852", "5853", "5854", "5855", "5856", "5864", "5865", "5866", "5872", "5874", "5876", "5877", "5880", "5881", "5882", "5888", "5889", "5891", "5893", "5894", "5895", "5896", "5898", "5901", "5902", "5904", "5905", "5906", "5907", "5909", "5914", "5915", "5917", "5918", "5920", "5921", "5924", "5925", "5926", "5929", "5930", "5931", "5933", "5934", "5935", "5937", "5941", "5943", "5944", "5946", "5947", "5950", "5955", "5957", "5958", "5960", "5962", "5963", "5966", "5967", "5971", "5973", "5976", "5980", "5981", "5982", "5985", "5987", "5988", "5989", "5990", "5998", "5999", "6002", "6008", "6009", "6011", "6013", "6016", "6019", "6023", "6025", "6028", "6030", "6033", "6035", "6037", "6038", "6039", "6040", "6041", "6043", "6046", "6047", "6050", "6052", "6058", "6059", "6062", "6063", "6064", "6065", "6066", "6067", "6071", "6074", "6076", "6078", "6079", "6082", "6083", "6085", "6087", "6088", "6089", "6091", "6092", "6093", "6094", "6097", "6099", "6105", "6106", "6107", "6111", "6112", "6118", "6120", "6121", "6122", "6123", "6124", "6126", "6130", "6131", "6132", "6135", "6137", "6138", "6139", "6140", "6141", "6142", "6145", "6146", "6147", "6149", "6152", "6153", "6154", "6155", "6161", "6163", "6165", "6166", "6167", "6178", "6181", "6184", "6186", "6188", "6190", "6192", "6195", "6196", "6200", "6203", "6208", "6210", "6212", "6214", "6216", "6217", "6225", "6227", "6228", "6231", "6232", "6235", "6240", "6241", "6244", "6246", "6249", "6250", "6251", "6253", "6254", "6255", "6256", "6257", "6258", "6262", "6264", "6267", "6268", "6271", "6272", "6274", "6275", "6276", "6278", "6279", "6281", "6282", "6283", "6284", "6291", "6292", "6293", "6294", "6298", "6300", "6301", "6304", "6305", "6306", "6307", "6309", "6311", "6312", "6314", "6315", "6316", "6319", "6321", "6326", "6332", "6334", "6335", "6339", "6340", "6341", "6346", "6348", "6350", "6354", "6355", "6356", "6357", "6360", "6363", "6364", "6366", "6367", "6369", "6370", "6374", "6376", "6381", "6385", "6386", "6388", "6390", "6392", "6396", "6397", "6400", "6401", "6403", "6405", "6406", "6407", "6408", "6413", "6414", "6416", "6419", "6422", "6424", "6427", "6428", "6429", "6431", "6432", "6436", "6441", "6443", "6445", "6446", "6451", "6452", "6454", "6456", "6460", "6462", "6464", "6466", "6468", "6469", "6470", "6471", "6472", "6473", "6475", "6477", "6478", "6483", "6485", "6487", "6488", "6491", "6492", "6494", "6497", "6499", "6500", "6502", "6504", "6507", "6509", "6512", "6513", "6516", "6521", "6523", "6527", "6528", "6529", "6530", "6533", "6534", "6535", "6537", "6539", "6540", "6541", "6542", "6543", "6544", "6545", "6546", "6547", "6550", "6552", "6555", "6557", "6558", "6560", "6563", "6565", "6567", "6568", "6569", "6570", "6573", "6574", "6576", "6578", "6580", "6582", "6583", "6585", "6586", "6587", "6588", "6589", "6593", "6596", "6597", "6605", "6608", "6609", "6611", "6612", "6613", "6615", "6617", "6618", "6619", "6622", "6623", "6624", "6626", "6629", "6630", "6635", "6636", "6637", "6638", "6639", "6641", "6642", "6643", "6644", "6650", "6652", "6653", "6654", "6665", "6667", "6668", "6669", "6670", "6672", "6674", "6678", "6679", "6680", "6682", "6684", "6686", "6687", "6688", "6691", "6695", "6696", "6697", "6698", "6699", "6700", "6709", "6711", "6712", "6713", "6717", "6718", "6719", "6721", "6722", "6723", "6724", "6725", "6727", "6730", "6731", "6732", "6735", "6736", "6740", "6742", "6745", "6750", "6751", "6754", "6755", "6756", "6758", "6759", "6760", "6767", "6768", "6774", "6775", "6777", "6779", "6780", "6781", "6782", "6784", "6785", "6786", "6787", "6788", "6790", "6794", "6795", "6796", "6797", "6803", "6805", "6809", "6810", "6812", "6813", "6814", "6815", "6816", "6817", "6819", "6820", "6824", "6825", "6826", "6829", "6831", "6836", "6839", "6840", "6842", "6843", "6845", "6846", "6847", "6849", "6853", "6857", "6858", "6860", "6861", "6862", "6863", "6864", "6869", "6870", "6874", "6876", "6880", "6884", "6885", "6888", "6890", "6892", "6893", "6898", "6899", "6902", "6904", "6910", "6911", "6912", "6913", "6915", "6918", "6919", "6920", "6921", "6924", "6925", "6927", "6928", "6933", "6934", "6935", "6938", "6941", "6942", "6944", "6951", "6952", "6955", "6956", "6957", "6959", "6960", "6966", "6970", "6972", "6976", "6977", "6979", "6980", "6981", "6982", "6984", "6987", "6988", "6989", "6992", "6994", "6995", "6998", "6999", "7004", "7006", "7007", "7009", "7010", "7011", "7012", "7020", "7022", "7025", "7026", "7028", "7034", "7035", "7037", "7041", "7042", "7046", "7048", "7050", "7053", "7054", "7056", "7057", "7058", "7059", "7062", "7064", "7065", "7066", "7067", "7069", "7070", "7071", "7073", "7074", "7075", "7076", "7078", "7079", "7086", "7087", "7089", "7092", "7096", "7097", "7101", "7102", "7105", "7107", "7108", "7111", "7113", "7114", "7115", "7116", "7118", "7119", "7127", "7128", "7130", "7133", "7137", "7138", "7140", "7141", "7143", "7144", "7145", "7146", "7147", "7149", "7150", "7151", "7155", "7156", "7162", "7164", "7167", "7170", "7171", "7172", "7174", "7175", "7177", "7181", "7182", "7185", "7191", "7193", "7194", "7195", "7196", "7198", "7199", "7201", "7208", "7209", "7210", "7211", "7215", "7219", "7220", "7230", "7232", "7233", "7235", "7238", "7239", "7242", "7246", "7247", "7248", "7249", "7254", "7255", "7258", "7261", "7262", "7263", "7264", "7265", "7266", "7268", "7269", "7272", "7277", "7282", "7283", "7284", "7285", "7287", "7288", "7289", "7290", "7295", "7296", "7297", "7300", "7302", "7303", "7310", "7311", "7313", "7317", "7321", "7322", "7324", "7326", "7328", "7330", "7331", "7333", "7337", "7340", "7341", "7347", "7349", "7352", "7353", "7357", "7358", "7360", "7362", "7367", "7370", "7372", "7374", "7379", "7380", "7381", "7383", "7385", "7386", "7388", "7391", "7392", "7395", "7396", "7398", "7399", "7401", "7402", "7405", "7407", "7408", "7409", "7410", "7412", "7413", "7417", "7419", "7420", "7422", "7423", "7425", "7426", "7428", "7430", "7432", "7436", "7437", "7440", "7442", "7443", "7444", "7445", "7446", "7448", "7449", "7451", "7452", "7453", "7454", "7455", "7456", "7459", "7460", "7461", "7462", "7463", "7464", "7466", "7468", "7469", "7470", "7471", "7472", "7473", "7478", "7479", "7482", "7483", "7484", "7487", "7490", "7491", "7493", "7494", "7495", "7496", "7498", "7499", "7501", "7504", "7506", "7507", "7508", "7510", "7513", "7514", "7515", "7518", "7522", "7525", "7526", "7527", "7528", "7529", "7530", "7532", "7533", "7536", "7538", "7539", "7540", "7543", "7545", "7546", "7547", "7549", "7550", "7551", "7552", "7555", "7556", "7560", "7563", "7564", "7566", "7567", "7569", "7570", "7571", "7573", "7578", "7580", "7581", "7582", "7583", "7586", "7588", "7590", "7591", "7593", "7594", "7598", "7604", "7606", "7607", "7609", "7610", "7611", "7614", "7615", "7616", "7619", "7621", "7622", "7623", "7625", "7626", "7627", "7628", "7630", "7631", "7635", "7636", "7637", "7639", "7640", "7641", "7644", "7645", "7646", "7650", "7652", "7654", "7656", "7658", "7660", "7661", "7662", "7663", "7667", "7668", "7669", "7673", "7676", "7678", "7681", "7682", "7684", "7687", "7688", "7689", "7690", "7691", "7693", "7697", "7699", "7703", "7704", "7706", "7707", "7709", "7710", "7712", "7716", "7717", "7719", "7720", "7721", "7722", "7723", "7724", "7728", "7729", "7732", "7735", "7737", "7738", "7740", "7744", "7745", "7747", "7748", "7749", "7751", "7752", "7754", "7756", "7757", "7758", "7759", "7763", "7764", "7765", "7766", "7768", "7770", "7777", "7778", "7780", "7781", "7782", "7787", "7791", "7792", "7794", "7795", "7796", "7797", "7798", "7803", "7805", "7808", "7809", "7813", "7814", "7815", "7817", "7818", "7822", "7823", "7826", "7827", "7828", "7830", "7831", "7835", "7836", "7837", "7838", "7839", "7840", "7842", "7845", "7847", "7848", "7851", "7853", "7855", "7858", "7859", "7861", "7862", "7863", "7865", "7870", "7872", "7874", "7878", "7880", "7888", "7889", "7890", "7891", "7893", "7894", "7896", "7897", "7898", "7900", "7901", "7903", "7905", "7909", "7911", "7913", "7914", "7915", "7916", "7917", "7918", "7919", "7920", "7923", "7925", "7926", "7927", "7929", "7931", "7932", "7933", "7934", "7935", "7936", "7937", "7939", "7940", "7941", "7946", "7947", "7949", "7950", "7953", "7954", "7955", "7959", "7961", "7964", "7965", "7966", "7967", "7968", "7973", "7974", "7975", "7976", "7983", "7984", "7987", "7991", "7992", "7993", "7994", "7998", "7999", "8002", "8005", "8007", "8008", "8010", "8012", "8013", "8021", "8023", "8025", "8026", "8028", "8029", "8031", "8032", "8034", "8035", "8036", "8037", "8040", "8041", "8042", "8043", "8045", "8046", "8048", "8049", "8051", "8053", "8057", "8058", "8061", "8063", "8064", "8065", "8066", "8068", "8071", "8073", "8074", "8078", "8079", "8080", "8081", "8083", "8084", "8087", "8088", "8093", "8097", "8101", "8102", "8104", "8107", "8108", "8109", "8110", "8112", "8113", "8114", "8115", "8117", "8119", "8121", "8123", "8124", "8127", "8128", "8129", "8130", "8133", "8134", "8135", "8136", "8137", "8138", "8139", "8140", "8144", "8145", "8151", "8154", "8155", "8158", "8160", "8162", "8166", "8171", "8172", "8173", "8176", "8177", "8178", "8179", "8181", "8184", "8185", "8186", "8187", "8192", "8194", "8195", "8197", "8198", "8199", "8200", "8201", "8206", "8207", "8209", "8210", "8211", "8212", "8213", "8214", "8215", "8216", "8223", "8224", "8229", "8230", "8235", "8239", "8240", "8241", "8246", "8247", "8252", "8253", "8255", "8257", "8258", "8259", "8263", "8264", "8266", "8268", "8270", "8271", "8275", "8276", "8277", "8278", "8279", "8280", "8285", "8286", "8287", "8288", "8293", "8294", "8296", "8297", "8298", "8299", "8303", "8304", "8305", "8306", "8309", "8312", "8315", "8316", "8319", "8320", "8324", "8325", "8328", "8332", "8333", "8334", "8336", "8338", "8339", "8340", "8341", "8345", "8350", "8355", "8356", "8359", "8360", "8363", "8364", "8368", "8369", "8372", "8373", "8375", "8379", "8382", "8384", "8386", "8391", "8392", "8394", "8395", "8396", "8397", "8398", "8402", "8404", "8405", "8407", "8408", "8414", "8415", "8416", "8417", "8419", "8420", "8422", "8423", "8424", "8426", "8428", "8429", "8430", "8434", "8435", "8436", "8437", "8439", "8445", "8447", "8449", "8451", "8452", "8454", "8460", "8465", "8466", "8467", "8471", "8473", "8478", "8483", "8484", "8485", "8486", "8487", "8488", "8490", "8495", "8496", "8500", "8503", "8505", "8509", "8511", "8512", "8514", "8516", "8518", "8521", "8522", "8523", "8524", "8525", "8527", "8531", "8535", "8537", "8538", "8541", "8542", "8544", "8548", "8550", "8553", "8554", "8556", "8558", "8559", "8561", "8562", "8564", "8567", "8568", "8572", "8573", "8574", "8576", "8580", "8583", "8586", "8587", "8590", "8591", "8593", "8594", "8595", "8596", "8597", "8598", "8600", "8602", "8605", "8608", "8610", "8612", "8613", "8614", "8615", "8616", "8617", "8618", "8619", "8622", "8625", "8626", "8627", "8629", "8630", "8631", "8632", "8635", "8636", "8639", "8645", "8646", "8649", "8650", "8652", "8654", "8658", "8660", "8661", "8662", "8670", "8671", "8673", "8676", "8677", "8678", "8679", "8682", "8685", "8689", "8694", "8695", "8698", "8701", "8702", "8704", "8706", "8708", "8710", "8712", "8713", "8714", "8715", "8717", "8720", "8722", "8723", "8729", "8730", "8731", "8733", "8736", "8738", "8740", "8741", "8743", "8744", "8746", "8749", "8750", "8752", "8756", "8758", "8759", "8763", "8770", "8772", "8773", "8778", "8779", "8782", "8783", "8784", "8786", "8788", "8790", "8793", "8797", "8799", "8802", "8803", "8806", "8809", "8812", "8813", "8814", "8815", "8816", "8818", "8820", "8822", "8826", "8828", "8829", "8831", "8832", "8833", "8836", "8839", "8841", "8843", "8844", "8846", "8847", "8849", "8852", "8854", "8857", "8858", "8859", "8863", "8865", "8866", "8868", "8869", "8871", "8873", "8876", "8877", "8879", "8880", "8882", "8884", "8886", "8890", "8894", "8895", "8897", "8901", "8908", "8909", "8910", "8911", "8912", "8913", "8915", "8917", "8919", "8920", "8925", "8927", "8928", "8929", "8930", "8932", "8933", "8936", "8939", "8940", "8944", "8945", "8946", "8948", "8950", "8951", "8956", "8960", "8964", "8967", "8968", "8969", "8971", "8974", "8982", "8983", "8984", "8992", "8994", "8995", "8996", "8997", "9000", "9004", "9005", "9006", "9007", "9008", "9012", "9013", "9014", "9017", "9018", "9020", "9021", "9023", "9028", "9029", "9031", "9034", "9038", "9040", "9041", "9042", "9044", "9045", "9047", "9048", "9051", "9053", "9054", "9055", "9056", "9059", "9060", "9061", "9062", "9070", "9072", "9074", "9076", "9077", "9083", "9084", "9085", "9087", "9089", "9091", "9093", "9094", "9099", "9100", "9101", "9104", "9105", "9106", "9107", "9109", "9110", "9111", "9114", "9115", "9116", "9117", "9118", "9119", "9121", "9124", "9126", "9127", "9131", "9134", "9135", "9136", "9138", "9139", "9141", "9142", "9144", "9148", "9150", "9151", "9152", "9155", "9156", "9160", "9161", "9162", "9165", "9169", "9170", "9173", "9180", "9183", "9185", "9186", "9187", "9189", "9190", "9191", "9192", "9196", "9201", "9204", "9207", "9208", "9209", "9211", "9213", "9214", "9215", "9217", "9218", "9219", "9223", "9226", "9228", "9230", "9231", "9233", "9235", "9236", "9237", "9238", "9239", "9241", "9244", "9246", "9248", "9249", "9250", "9252", "9255", "9258", "9259", "9261", "9267", "9270", "9273", "9276", "9277", "9278", "9281", "9285", "9287", "9292", "9293", "9299", "9300", "9303", "9306", "9308", "9310", "9314", "9317", "9325", "9326", "9327", "9328", "9329", "9330", "9331", "9335", "9336", "9337", "9340", "9342", "9343", "9344", "9351", "9356", "9358", "9361", "9364", "9365", "9368", "9369", "9370", "9372", "9374", "9375", "9379", "9380", "9382", "9387", "9388", "9391", "9392", "9393", "9396", "9397", "9399", "9400", "9401", "9402", "9407", "9408", "9410", "9411", "9412", "9413", "9417", "9420", "9421", "9422", "9423", "9427", "9429", "9438", "9439", "9440", "9441", "9444", "9446", "9448", "9451", "9455", "9457", "9460", "9462", "9463", "9464", "9476", "9477", "9479", "9484", "9485", "9487", "9489", "9490", "9495", "9496", "9497", "9498", "9501", "9502", "9503", "9506", "9507", "9508", "9509", "9510", "9512", "9514", "9516", "9517", "9519", "9520", "9522", "9523", "9526", "9529", "9530", "9538", "9540", "9542", "9543", "9544", "9546", "9547", "9555", "9557", "9561", "9564", "9565", "9568", "9569", "9571", "9575", "9577", "9584", "9589", "9590", "9592", "9593", "9602", "9604", "9605", "9608", "9613", "9615", "9617", "9618", "9620", "9621", "9624", "9626", "9627", "9628", "9630", "9633", "9634", "9635", "9636", "9638", "9640", "9642", "9643", "9644", "9646", "9648", "9649", "9650", "9652", "9656", "9657", "9658", "9660", "9661", "9662", "9663", "9666", "9667", "9669", "9673", "9676", "9677", "9678", "9681", "9683", "9684", "9686", "9687", "9689", "9691", "9692", "9695", "9696", "9698", "9699", "9703", "9708", "9709", "9710", "9712", "9722", "9725", "9726", "9727", "9728", "9730", "9731", "9735", "9737", "9739", "9743", "9744", "9749", "9750", "9751", "9753", "9754", "9755", "9756", "9757", "9758", "9761", "9762", "9765", "9766", "9770", "9771", "9773", "9774", "9776", "9777", "9781", "9783", "9784", "9786", "9791", "9793", "9794", "9797", "9799", "9802", "9803", "9804", "9806", "9808", "9810", "9811", "9812", "9816", "9817", "9820", "9822", "9823", "9824", "9825", "9826", "9827", "9830", "9832", "9833", "9834", "9842", "9843", "9844", "9845", "9847", "9848", "9849", "9850", "9855", "9856", "9857", "9858", "9859", "9862", "9863", "9864", "9866", "9868", "9869", "9871", "9873", "9875", "9876", "9877", "9880", "9882", "9886", "9888", "9890", "9898", "9899", "9900", "9901", "9902", "9903", "9904", "9907", "9909", "9910", "9915", "9918", "9919", "9921", "9922", "9923", "9924", "9925", "9926", "9928", "9930", "9931", "9932", "9935", "9937", "9939", "9940", "9941", "9943", "9948", "9951", "9952", "9953", "9954", "9956", "9957", "9958", "9959", "9960", "9961", "9962", "9964", "9965", "9968", "9969", "9972", "9973", "9974", "9975", "9977", "9980", "9981", "9982", "9989", "9991", "9992", "9993", "9997", "9998", "10000", "10001", "10002", "10004", "10008", "10009", "10010", "10012", "10013", "10014", "10017", "10018", "10019", "10020", "10022", "10023", "10025", "10026", "10028", "10031", "10032", "10035", "10041", "10043", "10044", "10045", "10046", "10048", "10049", "10051", "10052", "10053", "10054", "10056", "10057", "10059", "10060", "10061", "10062", "10067", "10068", "10070", "10071", "10073", "10074", "10080", "10081", "10082", "10083", "10086", "10087", "10090", "10092", "10093", "10094", "10097", "10101", "10102", "10105", "10106", "10107", "10109", "10114", "10116", "10117", "10118", "10119", "10121", "10122", "10126", "10127", "10129", "10130", "10132", "10133", "10134", "10136", "10137", "10143", "10145", "10147", "10153", "10158", "10159", "10160", "10162", "10163", "10164", "10166", "10170", "10171", "10172", "10173", "10178", "10185", "10186", "10188", "10193", "10194", "10195", "10196", "10198", "10199", "10200", "10201", "10202", "10203", "10204", "10206", "10207", "10210", "10211", "10212", "10214", "10216", "10217", "10219", "10220", "10226", "10229", "10235", "10241", "10242", "10245", "10247", "10248", "10251", "10252", "10253", "10255", "10256", "10257", "10258", "10260", "10262", "10268", "10269", "10270", "10271", "10274", "10276", "10277", "10279", "10280", "10285", "10288", "10291", "10294", "10298", "10300", "10304", "10305", "10309", "10312", "10315", "10320", "10323", "10331", "10332", "10334", "10337", "10342", "10344", "10350", "10352", "10353", "10354", "10355", "10356", "10360", "10361", "10363", "10364", "10372", "10374", "10376", "10380", "10383", "10390", "10395", "10396", "10399", "10403", "10405", "10406", "10409", "10415", "10416", "10417", "10419", "10420", "10422", "10423", "10424", "10427", "10428", "10433", "10434", "10435", "10436", "10437", "10438", "10440", "10443", "10444", "10446", "10448", "10449", "10450", "10453", "10455", "10456", "10457", "10458", "10459", "10460", "10461", "10463", "10468", "10470", "10472", "10474", "10476", "10477", "10478", "10479", "10480", "10482", "10483", "10485", "10487", "10489", "10493", "10494", "10495", "10496", "10499", "10507", "10509", "10511", "10513", "10515", "10517", "10522", "10523", "10524", "10525", "10526", "10528", "10530", "10532", "10535", "10537", "10538", "10540", "10541", "10542", "10544", "10549", "10557", "10558", "10560", "10562", "10563", "10565", "10567", "10568", "10569", "10572", "10579", "10580", "10582", "10584", "10586", "10588", "10590", "10591", "10593", "10601", "10604", "10605", "10607", "10608", "10609", "10610", "10612", "10613", "10614", "10615", "10616", "10619", "10621", "10622", "10623", "10625", "10627", "10628", "10629", "10630", "10631", "10632", "10635", "10640", "10641", "10644", "10645", "10648", "10649", "10650", "10651", "10656", "10657", "10659", "10660", "10663", "10664", "10665", "10666", "10667", "10670", "10671", "10672", "10673", "10674", "10676", "10677", "10678", "10680", "10681", "10685", "10686", "10688", "10690", "10692", "10695", "10700", "10701", "10705", "10706", "10707", "10708", "10709", "10710", "10714", "10716", "10718", "10719", "10722", "10724", "10727", "10729", "10735", "10736", "10742", "10744", "10745", "10753", "10754", "10755", "10757", "10758", "10759", "10762", "10764", "10765", "10766", "10767", "10771", "10772", "10773", "10776", "10778", "10781", "10786", "10788", "10791", "10792", "10793", "10794", "10795", "10798", "10802", "10803", "10805", "10806", "10807", "10810", "10811", "10813", "10814", "10815", "10816", "10818", "10819", "10820", "10821", "10822", "10824", "10826", "10827", "10829", "10832", "10833", "10834", "10835", "10838", "10841", "10842", "10846", "10848", "10849", "10851", "10852", "10855", "10856", "10859", "10860", "10864", "10865", "10867", "10870", "10874", "10877", "10879", "10881", "10882", "10883", "10884", "10885", "10886", "10887", "10889", "10890", "10893", "10898", "10899", "10900", "10901", "10902", "10904", "10910", "10911", "10914", "10915", "10919", "10920", "10921", "10922", "10924", "10928", "10930", "10932", "10935", "10937", "10938", "10939", "10942", "10946", "10947", "10949", "10950", "10952", "10955", "10956", "10958", "10959", "10960", "10963", "10964", "10965", "10966", "10971", "10972", "10973", "10976", "10977", "10978", "10979", "10981", "10985", "10987", "10989", "10993", "10994", "10996", "10997", "10998", "10999", "11000", "11001", "11004", "11005", "11009", "11011", "11012", "11019", "11021", "11022", "11023", "11025", "11026", "11028", "11031", "11032", "11034", "11035", "11038", "11039", "11042", "11043", "11044", "11045", "11047", "11048", "11049", "11051", "11058", "11059", "11065", "11066", "11067", "11068", "11069", "11074", "11080", "11081", "11083", "11086", "11090", "11091", "11092", "11093", "11094", "11098", "11100", "11101", "11104", "11105", "11106", "11107", "11111", "11115", "11119", "11120", "11124", "11128", "11130", "11134", "11135", "11136", "11138", "11140", "11141", "11142", "11143", "11144", "11145", "11146", "11147", "11148", "11149", "11150", "11151", "11152", "11153", "11154", "11157", "11159", "11160", "11161", "11162", "11163", "11167", "11168", "11169", "11171", "11172", "11174", "11177", "11181", "11184", "11185", "11192", "11195", "11200", "11202", "11204", "11205", "11209", "11210", "11212", "11217", "11218", "11221", "11222", "11225", "11226", "11227", "11228", "11230", "11232", "11233", "11238", "11239", "11243", "11248", "11251", "11252", "11253", "11254", "11255", "11257", "11259", "11260", "11264", "11267", "11270", "11272", "11276", "11278", "11279", "11280", "11281", "11283", "11284", "11285", "11287", "11291", "11294", "11296", "11298", "11300", "11301", "11303", "11304", "11305", "11306", "11307", "11309", "11310", "11311", "11312", "11313", "11318", "11322", "11324", "11325", "11332", "11333", "11334", "11336", "11339", "11343", "11344", "11346", "11347", "11348", "11353", "11354", "11356", "11357", "11359", "11362", "11364", "11365", "11366", "11367", "11368", "11369", "11371", "11376", "11377", "11378", "11380", "11381", "11382", "11383", "11384", "11385", "11388", "11390", "11391", "11395", "11397", "11403", "11405", "11406", "11407", "11408", "11409", "11412", "11413", "11414", "11415", "11417", "11418", "11420", "11421", "11423", "11425", "11427", "11428", "11431", "11432", "11436", "11439", "11441", "11443", "11446", "11449", "11452", "11454", "11456", "11459", "11461", "11462", "11465", "11466", "11467", "11468", "11469", "11470", "11471", "11472", "11473", "11477", "11478", "11479", "11484", "11486", "11489", "11490", "11491", "11493", "11494", "11495", "11496", "11497", "11499", "11500", "11501", "11502", "11505", "11508", "11509", "11512", "11513", "11514", "11516", "11518", "11519", "11521", "11522", "11524", "11526", "11528", "11529", "11530", "11531", "11533", "11536", "11538", "11539", "11540", "11542", "11543", "11546", "11547", "11548", "11549", "11550", "11553", "11554", "11558", "11561", "11562", "11563", "11567", "11568", "11569", "11571", "11572", "11573", "11575", "11576", "11577", "11578", "11579", "11580", "11582", "11583", "11584", "11586", "11591", "11596", "11598", "11600", "11602", "11604", "11605", "11606", "11609", "11612", "11615", "11617", "11619", "11620", "11621", "11622", "11624", "11625", "11626", "11628", "11631", "11636", "11638", "11639", "11640", "11641", "11642", "11643", "11644", "11645", "11646", "11648", "11649", "11653", "11654", "11655", "11659", "11660", "11661", "11663", "11664", "11665", "11668", "11669", "11671", "11672", "11673", "11674", "11678", "11679", "11681", "11682", "11684", "11686", "11688", "11691", "11693", "11695", "11698", "11701", "11702", "11703", "11708", "11709", "11710", "11718", "11720", "11721", "11722", "11723", "11726", "11727", "11728", "11730", "11734", "11735", "11736", "11737", "11738", "11739", "11741", "11742", "11743", "11744", "11747", "11749", "11750", "11752", "11754", "11755", "11756", "11757", "11760", "11761", "11763", "11768", "11770", "11772", "11774", "11776", "11778", "11784", "11787", "11790", "11792", "11794", "11798", "11799", "11801", "11802", "11803", "11804", "11809", "11810", "11811", "11816", "11817", "11822", "11823", "11824", "11827", "11828", "11829", "11830", "11831", "11836", "11840", "11843", "11845", "11848", "11851", "11853", "11854", "11857", "11858", "11859", "11863", "11865", "11869", "11870", "11873", "11874", "11875", "11880", "11882", "11883", "11884", "11885", "11887", "11890", "11892", "11894", "11896", "11900", "11901", "11904", "11905", "11906", "11907", "11909", "11911", "11912", "11915", "11916", "11920", "11921", "11926", "11927", "11928", "11929", "11931", "11935", "11938", "11940", "11945", "11947", "11952", "11954", "11957", "11958", "11961", "11962", "11964", "11965", "11968", "11969", "11975", "11977", "11980", "11981", "11982", "11985", "11988", "11989", "11990", "11991", "11995", "11998", "12000", "12001", "12002", "12003", "12010", "12011", "12012", "12015", "12016", "12017", "12018", "12019", "12024", "12025", "12027", "12028", "12029", "12032", "12036", "12039", "12040", "12041", "12042", "12043", "12046", "12049", "12050", "12051", "12053", "12056", "12057", "12058", "12059", "12060", "12062", "12064", "12072", "12073", "12074", "12075", "12077", "12079", "12080", "12082", "12084", "12086", "12087", "12091", "12094", "12095", "12096", "12097", "12098", "12099", "12101", "12106", "12107", "12108", "12114", "12116", "12117", "12118", "12119", "12120", "12125", "12126", "12127", "12128", "12129", "12130", "12131", "12132", "12133", "12134", "12135", "12136", "12138", "12139", "12140", "12143", "12145", "12146", "12148", "12150", "12152", "12153", "12157", "12162", "12164", "12166", "12167", "12169", "12170", "12172", "12173", "12178", "12179", "12180", "12181", "12182", "12184", "12185", "12187", "12190", "12192", "12193", "12194", "12195", "12197", "12198", "12202", "12203", "12206", "12209", "12210", "12211", "12213", "12221", "12222", "12224", "12225", "12227", "12230", "12233", "12234", "12235", "12236", "12237", "12238", "12240", "12242", "12243", "12244", "12246", "12249", "12250", "12251", "12253", "12254", "12256", "12257", "12258", "12260", "12264", "12269", "12270", "12271", "12272", "12273", "12274", "12275", "12276", "12277", "12279", "12281", "12282", "12284", "12285", "12286", "12288", "12293", "12296", "12298", "12299", "12301", "12306", "12307", "12308", "12314", "12315", "12316", "12319", "12321", "12323", "12325", "12327", "12329", "12333", "12336", "12337", "12339", "12341", "12342", "12346", "12348", "12350", "12352", "12353", "12354", "12356", "12357", "12358", "12359", "12360", "12364", "12365", "12367", "12370", "12371", "12374", "12375", "12377", "12379", "12382", "12384", "12385", "12386", "12392", "12393", "12395", "12396", "12398", "12400", "12401", "12402", "12411", "12416", "12418", "12419", "12421", "12425", "12428", "12429", "12430", "12431", "12441", "12443", "12445", "12446", "12447", "12450", "12451", "12452", "12453", "12454", "12456", "12457", "12459", "12463", "12467", "12468", "12469", "12471", "12472", "12473", "12474", "12475", "12476", "12479", "12480", "12482", "12484", "12485", "12486", "12487", "12488", "12490", "12495", "12498", "12499", "12501", "12502", "12511", "12513", "12517", "12520", "12523", "12526", "12527", "12528", "12530", "12531", "12532", "12533", "12534", "12535", "12539", "12540", "12541", "12544", "12547", "12549", "12551", "12553", "12555", "12558", "12559", "12560", "12561", "12564", "12568", "12569", "12571", "12577", "12578", "12579", "12584", "12585", "12587", "12588", "12589", "12590", "12591", "12592", "12596", "12601", "12603", "12604", "12606", "12610", "12611", "12614", "12615", "12616", "12619", "12621", "12624", "12629", "12632", "12633", "12635", "12637", "12639", "12641", "12642", "12644", "12645", "12646", "12647", "12648", "12649", "12651", "12652", "12655", "12659", "12661", "12663", "12665", "12666", "12667", "12670", "12672", "12673", "12674", "12675", "12677", "12679", "12681", "12684", "12685", "12687", "12689", "12691", "12692", "12696", "12699", "12700", "12702", "12704", "12705", "12707", "12710", "12712", "12713", "12715", "12716", "12717", "12718", "12720", "12722", "12728", "12729", "12730", "12731", "12733", "12739", "12740", "12744", "12745", "12746", "12747", "12749", "12751", "12752", "12758", "12761", "12765", "12767", "12769", "12770", "12771", "12772", "12779", "12780", "12782", "12787", "12789", "12791", "12793", "12795", "12796", "12798", "12799", "12800", "12801", "12802", "12803", "12804", "12805", "12806", "12808", "12809", "12811", "12812", "12813", "12816", "12817", "12821", "12823", "12824", "12825", "12830", "12831", "12832", "12834", "12837", "12839", "12843", "12844", "12845", "12846", "12847", "12850", "12853", "12861", "12863", "12864", "12865", "12867", "12869", "12870", "12872", "12878", "12879", "12880", "12882", "12883", "12885", "12886", "12887", "12888", "12889", "12890", "12891", "12893", "12894", "12897", "12898", "12905", "12908", "12909", "12910", "12911", "12912", "12913", "12914", "12918", "12919", "12924", "12925", "12926", "12928", "12929", "12930", "12931", "12932", "12933", "12935", "12936", "12937", "12939", "12940", "12942", "12943", "12944", "12946", "12950", "12951", "12952", "12954", "12957", "12959", "12960", "12962", "12965", "12966", "12969", "12970", "12974", "12975", "12976", "12977", "12978", "12981", "12982", "12983", "12985", "12986", "12987", "12988", "12989", "12992", "12996", "12997", "13001", "13003", "13004", "13008", "13010", "13011", "13012", "13015", "13017", "13018", "13019", "13023", "13024", "13025", "13026", "13027", "13028", "13030", "13033", "13037", "13038", "13039", "13041", "13042", "13045", "13046", "13047", "13048", "13052", "13055", "13056", "13057", "13058", "13060", "13062", "13063", "13066", "13067", "13071", "13076", "13078", "13079", "13080", "13081", "13083", "13084", "13085", "13087", "13088", "13089", "13090", "13095", "13096", "13097", "13100", "13101", "13104", "13107", "13108", "13111", "13112", "13114", "13115", "13116", "13117", "13118", "13124", "13126", "13127", "13131", "13133", "13134", "13137", "13142", "13143", "13146", "13147", "13148", "13149", "13151", "13152", "13155", "13158", "13160", "13162", "13163", "13164", "13168", "13169", "13171", "13172", "13174", "13175", "13176", "13181", "13182", "13184", "13185", "13186", "13187", "13189", "13190", "13193", "13195", "13196", "13200", "13201", "13202", "13206", "13207", "13208", "13209", "13211", "13212", "13214", "13217", "13220", "13221", "13224", "13227", "13231", "13232", "13237", "13238", "13240", "13243", "13244", "13247", "13249", "13250", "13252", "13254", "13256", "13258", "13259", "13266", "13267", "13269", "13270", "13274", "13276", "13277", "13278", "13279", "13280", "13284", "13286", "13288", "13289", "13290", "13292", "13293", "13295", "13296", "13297", "13300", "13301", "13303", "13307", "13308", "13310", "13313", "13317", "13318", "13321", "13324", "13328", "13330", "13331", "13334", "13337", "13338", "13339", "13341", "13346", "13347", "13349", "13351", "13358", "13361", "13362", "13370", "13371", "13372", "13374", "13376", "13377", "13378", "13379", "13381", "13382", "13384", "13386", "13387", "13388", "13390", "13391", "13392", "13394", "13395", "13396", "13399", "13402", "13407", "13408", "13410", "13416", "13417", "13419", "13422", "13424", "13425", "13426", "13427", "13429", "13430", "13431", "13432", "13433", "13434", "13435", "13436", "13437", "13438", "13439", "13441", "13442", "13445", "13448", "13449", "13450", "13451", "13452", "13454", "13455", "13456", "13458", "13460", "13462", "13463", "13472", "13473", "13474", "13475", "13476", "13477", "13480", "13481", "13482", "13483", "13484", "13485", "13486", "13488", "13489", "13492", "13493", "13495", "13496", "13499", "13500", "13501", "13502", "13503", "13504", "13506", "13507", "13509", "13511", "13514", "13519", "13521", "13522", "13523", "13526", "13527", "13528", "13529", "13530", "13537", "13538", "13539", "13540", "13543", "13544", "13545", "13551", "13552", "13553", "13557", "13558", "13560", "13561", "13565", "13566", "13567", "13568", "13569", "13570", "13571", "13572", "13573", "13574", "13575", "13576", "13586", "13587", "13589", "13590", "13592", "13594", "13595", "13596", "13599", "13600", "13601", "13602", "13604", "13610", "13615", "13623", "13626", "13627", "13628", "13629", "13631", "13634", "13635", "13637", "13638", "13639", "13640", "13641", "13642", "13643", "13645", "13646", "13650", "13653", "13654", "13656", "13657", "13658", "13660", "13661", "13664", "13665", "13666", "13667", "13672", "13673", "13674", "13675", "13680", "13682", "13683", "13685", "13686", "13690", "13692", "13695", "13698", "13702", "13704", "13710", "13712", "13714", "13715", "13716", "13718", "13720", "13722", "13723", "13726", "13730", "13731", "13732", "13733", "13734", "13735", "13744", "13745", "13747", "13748", "13751", "13756", "13758", "13759", "13761", "13762", "13763", "13768", "13769", "13770", "13774", "13777", "13778", "13779", "13785", "13786", "13788", "13789", "13790", "13791", "13792", "13795", "13800", "13803", "13805", "13808", "13811", "13812", "13813", "13819", "13821", "13822", "13824", "13826", "13828", "13830", "13831", "13832", "13834", "13835", "13836", "13837", "13843", "13846", "13847", "13848", "13849", "13853", "13854", "13857", "13861", "13866", "13868", "13870", "13871", "13875", "13877", "13878", "13879", "13885", "13889", "13892", "13893", "13894", "13895", "13896", "13898", "13899", "13904", "13907", "13908", "13910", "13911", "13915", "13916", "13917", "13918", "13922", "13924", "13925", "13927", "13928", "13930", "13932", "13936", "13940", "13942", "13944", "13946", "13948", "13949", "13953", "13956", "13960", "13961", "13962", "13965", "13967", "13973", "13976", "13977", "13978", "13980", "13984", "13988", "13990", "13993", "13994", "13995", "13997", "13999", "14001", "14004", "14005", "14008", "14010", "14011", "14013", "14014", "14016", "14018", "14020", "14021", "14024", "14025", "14026", "14030", "14031", "14035", "14037", "14040", "14042", "14043", "14044", "14045", "14048", "14049", "14051", "14053", "14056", "14060", "14061", "14062", "14063", "14065", "14068", "14069", "14071", "14072", "14073", "14074", "14075", "14076", "14080", "14085", "14087", "14088", "14089", "14090", "14095", "14096", "14098", "14099", "14100", "14104", "14106", "14108", "14112", "14113", "14117", "14120", "14121", "14122", "14123", "14125", "14127", "14128", "14130", "14132", "14133", "14134", "14139", "14141", "14145", "14148", "14149", "14151", "14158", "14159", "14160", "14161", "14164", "14169", "14170", "14171", "14173", "14174", "14177", "14178", "14179", "14182", "14186", "14187", "14188", "14190", "14192", "14201", "14204", "14208", "14214", "14218", "14220", "14223", "14224", "14225", "14226", "14227", "14228", "14229", "14231", "14233", "14235", "14236", "14238", "14240", "14243", "14245", "14246", "14249", "14250", "14251", "14253", "14255", "14258", "14260", "14261", "14265", "14266", "14268", "14270", "14273", "14274", "14275", "14276", "14278", "14279", "14280", "14282", "14286", "14289", "14293", "14295", "14296", "14298", "14299", "14300", "14302", "14308", "14310", "14311", "14312", "14314", "14316", "14317", "14319", "14321", "14326", "14327", "14328", "14329", "14330", "14331", "14332", "14336", "14337", "14338", "14340", "14341", "14344", "14345", "14349", "14352", "14353", "14355", "14356", "14357", "14358", "14359", "14361", "14362", "14364", "14365", "14366", "14367", "14368", "14369", "14371", "14372", "14373", "14374", "14376", "14380", "14382", "14385", "14386", "14388", "14391", "14393", "14394", "14396", "14399", "14402", "14406", "14411", "14412", "14413", "14414", "14418", "14422", "14425", "14426", "14428", "14433", "14435", "14437", "14439", "14440", "14441", "14443", "14444", "14445", "14448", "14449", "14453", "14455", "14456", "14457", "14458", "14459", "14460", "14461", "14462", "14463", "14465", "14466", "14467", "14468", "14469", "14470", "14471", "14472", "14474", "14475", "14476", "14478", "14485", "14487", "14489", "14490", "14492", "14493", "14494", "14497", "14499", "14500", "14501", "14502", "14507", "14508", "14510", "14511", "14512", "14513", "14514", "14515", "14516", "14517", "14518", "14519", "14520", "14521", "14522", "14523", "14526", "14527", "14528", "14529", "14530", "14531", "14534", "14535", "14536", "14538", "14539", "14540", "14542", "14543", "14544", "14551", "14552", "14553", "14554", "14555", "14557", "14558", "14559", "14560", "14561", "14563", "14564", "14565", "14568", "14569", "14573", "14574", "14575", "14578", "14580", "14581", "14583", "14589", "14591", "14592", "14593", "14594", "14599", "14603", "14604", "14606", "14607", "14608", "14609", "14610", "14611", "14614", "14615", "14617", "14618", "14621", "14622", "14625", "14626", "14627", "14629", "14631", "14632", "14633", "14634", "14635", "14636", "14638", "14639", "14640", "14644", "14648", "14650", "14651", "14653", "14655", "14657", "14658", "14659", "14661", "14662", "14664", "14666", "14667", "14668", "14672", "14679", "14683", "14684", "14686", "14688", "14690", "14694", "14695", "14696", "14697", "14699", "14700", "14701", "14706", "14708", "14709", "14710", "14712", "14714", "14716", "14721", "14722", "14723", "14725", "14726", "14727", "14728", "14733", "14734", "14735", "14736", "14737", "14738", "14739", "14740", "14741", "14742", "14743", "14744", "14747", "14748", "14750", "14752", "14756", "14760", "14761", "14762", "14764", "14765", "14768", "14771", "14772", "14773", "14776", "14777", "14778", "14780", "14781", "14782", "14783", "14784", "14786", "14791", "14793", "14794", "14801", "14802", "14804", "14805", "14810", "14812", "14813", "14814", "14815", "14816", "14817", "14819", "14822", "14824", "14825", "14827", "14828", "14830", "14831", "14832", "14834", "14837", "14842", "14844", "14847", "14848", "14850", "14851", "14853", "14854", "14859", "14862", "14864", "14866", "14867", "14869", "14874", "14876", "14878", "14880", "14882", "14883", "14884", "14885", "14886", "14887", "14889", "14891", "14895", "14897", "14898", "14899", "14900", "14905", "14908", "14912", "14914", "14916", "14917", "14920", "14925", "14926", "14928", "14930", "14933", "14936", "14939", "14941", "14942", "14943", "14945", "14947", "14948", "14949", "14954", "14955", "14957", "14960", "14961", "14963", "14965", "14966", "14968", "14971", "14979", "14980", "14984", "14986", "14987", "14988", "14990", "14996", "15001", "15003", "15004", "15009", "15011", "15012", "15014", "15016", "15017", "15021", "15024", "15025", "15027", "15028", "15029", "15030", "15033", "15034", "15036", "15037", "15038", "15040", "15041", "15042", "15044", "15046", "15047", "15049", "15052", "15053", "15054", "15059", "15061", "15062", "15064", "15065", "15066", "15067", "15068", "15069", "15070", "15073", "15075", "15081", "15083", "15088", "15091", "15093", "15095", "15097", "15098", "15100", "15103", "15104", "15105", "15106", "15107", "15110", "15111", "15112", "15113", "15115", "15123", "15124", "15126", "15129", "15130", "15131", "15132", "15133", "15134", "15135", "15136", "15137", "15141", "15143", "15144", "15145", "15147", "15149", "15151", "15152", "15153", "15155", "15156", "15157", "15158", "15159", "15160", "15161", "15162", "15163", "15166", "15167", "15169", "15170", "15173", "15175", "15176", "15177", "15178", "15179", "15181", "15182", "15184", "15186", "15190", "15191", "15195", "15196", "15198", "15200", "15201", "15204", "15206", "15207", "15208", "15209", "15211", "15212", "15213", "15216", "15217", "15218", "15220", "15222", "15223", "15228", "15229", "15230", "15232", "15233", "15236", "15237", "15238", "15242", "15244", "15245", "15249", "15250", "15251", "15253", "15255", "15260", "15261", "15264", "15265", "15267", "15268", "15269", "15270", "15271", "15273", "15276", "15277", "15279", "15281", "15283", "15285", "15286", "15287", "15288", "15289", "15291", "15292", "15294", "15301", "15302", "15305", "15308", "15313", "15314", "15316", "15317", "15318", "15319", "15321", "15322", "15323", "15325", "15326", "15327", "15328", "15329", "15330", "15332", "15334", "15335", "15336", "15338", "15339", "15341", "15343", "15346", "15349", "15354", "15356", "15357", "15358", "15362", "15367", "15370", "15374", "15376", "15379", "15382", "15387", "15388", "15391", "15392", "15393", "15394", "15397", "15399", "15401", "15405", "15407", "15410", "15412", "15413", "15416", "15417", "15419", "15420", "15421", "15422", "15424", "15426", "15427", "15429", "15431", "15433", "15436", "15437", "15442", "15444", "15448", "15451", "15452", "15453", "15454", "15458", "15459", "15460", "15461", "15464", "15466", "15469", "15472", "15474", "15475", "15476", "15479", "15483", "15486", "15487", "15488", "15490", "15491", "15492", "15494", "15495", "15496", "15501", "15503", "15504", "15506", "15507", "15508", "15510", "15511", "15513", "15514", "15515", "15516", "15517", "15518", "15520", "15522", "15525", "15527", "15528", "15529", "15532", "15533", "15534", "15535", "15538", "15541", "15543", "15545", "15547", "15549", "15551", "15552", "15553", "15554", "15555", "15557", "15559", "15562", "15564", "15565", "15566", "15567", "15568", "15571", "15573", "15579", "15580", "15581", "15582", "15585", "15586", "15587", "15589", "15591", "15596", "15597", "15599", "15600", "15601", "15604", "15605", "15607", "15609", "15610", "15613", "15614", "15619", "15620", "15624", "15625", "15630", "15632", "15633", "15636", "15637", "15639", "15642", "15645", "15646", "15647", "15649", "15650", "15652", "15655", "15657", "15658", "15660", "15661", "15664", "15666", "15670", "15671", "15674", "15675", "15676", "15679", "15681", "15682", "15685", "15686", "15688", "15691", "15692", "15693", "15694", "15700", "15703", "15706", "15707", "15708", "15709", "15712", "15713", "15714", "15715", "15718", "15719", "15720", "15724", "15730", "15732", "15735", "15737", "15739", "15740", "15741", "15747", "15748", "15749", "15753", "15754", "15756", "15760", "15761", "15763", "15764", "15766", "15767", "15768", "15771", "15772", "15779", "15781", "15783", "15784", "15785", "15786", "15787", "15788", "15794", "15796", "15797", "15798", "15800", "15802", "15803", "15806", "15807", "15813", "15815", "15817", "15823", "15824", "15826", "15827", "15831", "15832", "15833", "15836", "15837", "15839", "15841", "15844", "15846", "15847", "15849", "15850", "15852", "15854", "15856", "15857", "15858", "15859", "15861", "15862", "15864", "15866", "15867", "15870", "15875", "15876", "15877", "15878", "15880", "15882", "15884", "15887", "15890", "15892", "15893", "15895", "15897", "15898", "15900", "15901", "15902", "15903", "15904", "15906", "15907", "15908", "15909", "15913", "15914", "15915", "15916", "15918", "15922", "15923", "15924", "15925", "15926", "15927", "15928", "15931", "15932", "15934", "15936", "15937", "15938", "15939", "15940", "15941", "15947", "15948", "15949", "15950", "15952", "15953", "15955", "15956", "15959", "15960", "15961", "15963", "15965", "15970", "15973", "15974", "15975", "15976", "15978", "15979", "15980", "15983", "15986", "15989", "15991", "15992", "15993", "15995", "15997", "15998", "16001", "16002", "16003", "16005", "16008", "16009", "16010", "16012", "16013", "16016", "16018", "16020", "16021", "16023", "16024", "16025", "16027", "16030", "16031", "16033", "16034", "16037", "16039", "16040", "16042", "16043", "16044", "16045", "16047", "16048", "16049", "16050", "16052", "16053", "16055", "16056", "16057", "16058", "16061", "16063", "16065", "16066", "16068", "16070", "16071", "16072", "16075", "16078", "16080", "16081", "16082", "16085", "16086", "16089", "16090", "16091", "16096", "16097", "16100", "16101", "16106", "16108", "16110", "16112", "16114", "16115", "16116", "16121", "16123", "16124", "16125", "16127", "16128", "16130", "16134", "16136", "16137", "16139", "16140", "16142", "16143", "16145", "16147", "16148", "16151", "16152", "16154", "16155", "16156", "16157", "16158", "16162", "16163", "16167", "16168", "16169", "16170", "16172", "16175", "16178", "16180", "16181", "16183", "16185", "16186", "16188", "16189", "16191", "16192", "16194", "16197", "16199", "16201", "16204", "16206", "16208", "16209", "16210", "16211", "16215", "16216", "16218", "16219", "16225", "16227", "16228", "16232", "16234", "16235", "16237", "16239", "16240", "16243", "16248", "16249", "16251", "16254", "16256", "16259", "16262", "16263", "16264", "16266", "16269", "16270", "16271", "16273", "16274", "16275", "16276", "16278", "16279", "16282", "16285", "16287", "16289", "16291", "16292", "16293", "16294", "16299", "16300", "16303", "16304", "16306", "16308", "16309", "16310", "16311", "16312", "16313", "16314", "16315", "16316", "16318", "16320", "16321", "16322", "16323", "16325", "16326", "16329", "16333", "16334", "16335", "16339", "16340", "16341", "16344", "16346", "16347", "16348", "16349", "16350", "16351", "16352", "16353", "16357", "16359", "16360", "16362", "16363", "16364", "16365", "16367", "16373", "16374", "16375", "16376", "16378", "16382", "16383", "16385", "16386", "16387", "16388", "16397", "16398", "16401", "16402", "16403", "16406", "16408", "16412", "16413", "16415", "16416", "16417", "16419", "16420", "16421", "16423", "16424", "16429", "16431", "16433", "16439", "16440", "16441", "16443", "16448", "16452", "16453", "16454", "16455", "16457", "16459", "16460", "16462", "16463", "16465", "16467", "16468", "16469", "16470", "16471", "16472", "16474", "16475", "16476", "16477", "16478", "16479", "16485", "16488", "16493", "16496", "16499", "16500", "16503", "16505", "16506", "16510", "16512", "16515", "16517", "16522", "16523", "16524", "16526", "16527", "16528", "16530", "16531", "16532", "16534", "16535", "16536", "16537", "16538", "16541", "16544", "16545", "16546", "16548", "16550", "16552", "16553", "16555", "16556", "16558", "16559", "16563", "16565", "16567", "16569", "16574", "16575", "16576", "16577", "16579", "16580", "16581", "16584", "16585", "16588", "16591", "16592", "16594", "16596", "16597", "16599", "16600", "16601", "16604", "16605", "16606", "16610", "16611", "16612", "16613", "16615", "16616", "16617", "16618", "16624", "16626", "16627", "16631", "16633", "16634", "16635", "16636", "16640", "16642", "16648", "16651", "16653", "16655", "16656", "16657", "16658", "16659", "16660", "16663", "16664", "16666", "16667", "16668", "16670", "16674", "16675", "16676", "16677", "16681", "16683", "16687", "16689", "16691", "16692", "16693", "16694", "16696", "16699", "16700", "16701", "16702", "16704", "16706", "16710", "16711", "16712", "16713", "16714", "16715", "16716", "16720", "16724", "16725", "16727", "16729", "16730", "16734", "16735", "16736", "16745", "16749", "16755", "16760", "16761", "16764", "16767", "16768", "16769", "16772", "16773", "16775", "16777", "16778", "16780", "16781", "16782", "16784", "16785", "16786", "16787", "16789", "16795", "16799", "16801", "16802", "16803", "16806", "16807", "16810", "16816", "16819", "16820", "16821", "16822", "16824", "16825", "16827", "16828", "16835", "16836", "16837", "16839", "16840", "16841", "16845", "16846", "16847", "16848", "16849", "16851", "16852", "16853", "16854", "16856", "16859", "16860", "16861", "16862", "16863", "16864", "16866", "16869", "16871", "16875", "16878", "16879", "16880", "16881", "16882", "16883", "16887", "16888", "16892", "16893", "16894", "16898", "16901", "16902", "16906", "16907", "16910", "16911", "16912", "16914", "16920", "16921", "16924", "16926", "16933", "16938", "16939", "16940", "16941", "16942", "16945", "16947", "16948", "16949", "16950", "16952", "16953", "16958", "16961", "16964", "16965", "16966", "16967", "16973", "16974", "16975", "16976", "16977", "16979", "16982", "16985", "16986", "16988", "16991", "16992", "16993", "16994", "16998", "17002", "17003", "17004", "17005", "17006", "17007", "17009", "17012", "17013", "17014", "17015", "17017", "17020", "17022", "17023", "17024", "17028", "17029", "17032", "17033", "17034", "17035", "17036", "17041", "17043", "17044", "17045", "17047", "17051", "17052", "17053", "17054", "17055", "17057", "17059", "17060", "17061", "17063", "17065", "17066", "17068", "17069", "17070", "17071", "17073", "17074", "17075", "17076", "17077", "17079", "17080", "17081", "17086", "17089", "17091", "17092", "17093", "17094", "17096", "17098", "17099", "17101", "17102", "17104", "17105", "17106", "17109", "17111", "17114", "17116", "17117", "17118", "17119", "17122", "17125", "17128", "17133", "17135", "17136", "17138", "17140", "17141", "17144", "17145", "17146", "17147", "17150", "17151", "17152", "17154", "17156", "17157", "17159", "17163", "17166", "17168", "17170", "17172", "17174", "17175", "17178", "17179", "17182", "17183", "17187", "17188", "17190", "17191", "17193", "17196", "17198", "17200", "17201", "17202", "17203", "17205", "17206", "17208", "17210", "17213", "17215", "17216", "17218", "17219", "17220", "17224", "17225", "17231", "17233", "17234", "17235", "17239", "17240", "17242", "17245", "17246", "17247", "17249", "17251", "17256", "17257", "17258", "17259", "17260", "17263", "17265", "17267", "17269", "17271", "17272", "17276", "17279", "17286", "17287", "17288", "17289", "17291", "17292", "17295", "17297", "17299", "17300", "17301", "17302", "17303", "17304", "17305", "17306", "17308", "17309", "17310", "17312", "17313", "17315", "17317", "17319", "17320", "17324", "17327", "17328", "17332", "17335", "17338", "17345", "17346", "17349", "17350", "17352", "17356", "17359", "17361", "17362", "17364", "17365", "17368", "17370", "17372", "17375", "17378", "17381", "17382", "17390", "17391", "17392", "17393", "17397", "17398", "17399", "17401", "17403", "17407", "17412", "17414", "17415", "17416", "17417", "17419", "17420", "17421", "17422", "17423", "17424", "17425", "17426", "17428", "17430", "17431", "17434", "17435", "17436", "17438", "17440", "17442", "17443", "17449", "17454", "17457", "17460", "17463", "17465", "17467", "17469", "17471", "17474", "17475", "17479", "17480", "17482", "17485", "17486", "17488", "17489", "17490", "17492", "17496", "17497", "17498", "17499", "17500", "17501", "17502", "17505", "17506", "17508", "17509", "17510", "17511", "17512", "17517", "17520", "17521", "17525", "17526", "17528", "17529", "17530", "17531", "17532", "17533", "17534", "17536", "17538", "17539", "17545", "17547", "17548", "17549", "17550", "17551", "17554", "17556", "17558", "17559", "17562", "17563", "17564", "17565", "17566", "17567", "17568", "17569", "17570", "17571", "17572", "17573", "17578", "17580", "17581", "17583", "17584", "17587", "17590", "17593", "17595", "17597", "17598", "17599", "17602", "17603", "17604", "17608", "17609", "17613", "17615", "17617", "17620", "17621", "17622", "17626", "17627", "17628", "17632", "17633", "17634", "17635", "17637", "17638", "17640", "17641", "17642", "17643", "17644", "17646", "17648", "17650", "17651", "17653", "17656", "17657", "17658", "17659", "17660", "17661", "17664", "17665", "17667", "17669", "17670", "17672", "17675", "17677", "17678", "17683", "17686", "17690", "17691", "17693", "17694", "17695", "17697", "17700", "17701", "17702", "17707", "17708", "17713", "17714", "17715", "17716", "17719", "17721", "17722", "17723", "17725", "17726", "17727", "17728", "17732", "17733", "17734", "17735", "17736", "17737", "17739", "17742", "17745", "17747", "17748", "17749", "17750", "17751", "17753", "17757", "17759", "17760", "17761", "17762", "17769", "17771", "17773", "17775", "17776", "17777", "17781", "17783", "17784", "17786", "17790", "17791", "17792", "17794", "17797", "17798", "17799", "17800", "17801", "17802", "17803", "17806", "17810", "17811", "17813", "17814", "17817", "17818", "17819", "17820", "17821", "17822", "17823", "17824", "17825", "17827", "17829", "17830", "17833", "17834", "17835", "17837", "17838", "17839", "17840", "17841", "17842", "17845", "17846", "17847", "17848", "17849", "17850", "17852", "17854", "17855", "17858", "17860", "17862", "17864", "17865", "17867", "17868", "17869", "17872", "17874", "17875", "17876", "17880", "17883", "17884", "17885", "17886", "17887", "17888", "17892", "17893", "17895", "17897", "17901", "17902", "17903", "17904", "17906", "17907", "17909", "17912", "17919", "17920", "17924", "17926", "17928", "17929", "17930", "17931", "17936", "17937", "17938", "17939", "17940", "17945", "17947", "17948", "17949", "17950", "17951", "17952", "17954", "17955", "17958", "17960", "17961", "17964", "17966", "17968", "17972", "17976", "17977", "17980", "17983", "17984", "17986", "17989", "17990", "17991", "17994", "17995", "17998", "17999", "18000", "18006", "18009", "18010", "18011", "18012", "18014", "18016", "18017", "18018", "18019", "18020", "18023", "18024", "18032", "18033", "18034", "18035", "18037", "18038", "18041", "18046", "18048", "18051", "18053", "18054", "18056", "18057", "18059", "18060", "18069", "18072", "18074", "18075", "18076", "18079", "18081", "18083", "18084", "18085", "18095", "18101", "18103", "18107", "18108", "18109", "18110", "18115", "18116", "18117", "18118", "18120", "18122", "18123", "18124", "18126", "18127", "18128", "18130", "18134", "18135", "18139", "18141", "18143", "18149", "18150", "18151", "18155", "18156", "18157", "18161", "18163", "18164", "18166", "18168", "18170", "18172", "18173", "18175", "18177", "18178", "18179", "18185", "18186", "18187", "18188", "18190", "18194", "18195", "18197", "18198", "18199", "18200", "18202", "18204", "18206", "18207", "18209", "18210", "18217", "18220", "18221", "18222", "18223", "18224", "18225", "18227", "18228", "18229", "18230", "18231", "18234", "18235", "18239", "18241", "18246", "18249", "18250", "18254", "18258", "18260", "18261", "18263", "18264", "18266", "18267", "18269", "18273", "18274", "18276", "18277", "18278", "18279", "18280", "18284", "18286", "18287", "18289", "18291", "18293", "18294", "18299", "18307", "18309", "18311", "18312", "18315", "18316", "18317", "18319", "18320", "18321", "18322", "18323", "18324", "18326", "18328", "18329", "18331", "18334", "18336", "18342", "18346", "18347", "18348", "18350", "18351", "18353", "18357", "18358", "18360", "18363", "18367", "18368", "18370", "18371", "18374", "18376", "18377", "18378", "18380", "18381", "18382", "18385", "18387", "18388", "18389", "18391", "18394", "18400", "18402", "18403", "18406", "18410", "18411", "18412", "18413", "18414", "18415", "18417", "18419", "18420", "18421", "18422", "18424", "18425", "18426", "18427", "18428", "18431", "18432", "18433", "18434", "18435", "18437", "18440", "18442", "18445", "18446", "18447", "18449", "18456", "18459", "18460", "18462", "18463", "18467", "18469", "18470", "18471", "18472", "18474", "18476", "18477", "18479", "18480", "18481", "18482", "18483", "18486", "18493", "18497", "18498", "18499", "18501", "18502", "18503", "18504", "18507", "18509", "18513", "18515", "18519", "18520", "18528", "18529", "18530", "18531", "18535", "18537", "18538", "18540", "18541", "18542", "18544", "18545", "18547", "18548", "18553", "18554", "18556", "18557", "18561", "18562", "18564", "18568", "18571", "18573", "18576", "18578", "18580", "18581", "18585", "18588", "18589", "18592", "18593", "18594", "18595", "18596", "18597", "18598", "18599", "18601", "18604", "18607", "18609", "18611", "18613", "18617", "18618", "18620", "18622", "18624", "18625", "18626", "18628", "18629", "18630", "18632", "18633", "18638", "18639", "18640", "18642", "18644", "18646", "18649", "18650", "18651", "18655", "18658", "18661", "18664", "18668", "18669", "18670", "18671", "18674", "18675", "18676", "18681", "18683", "18688", "18691", "18692", "18693", "18696", "18697", "18699", "18700", "18701", "18702", "18706", "18707", "18711", "18712", "18713", "18714", "18715", "18720", "18721", "18722", "18724", "18726", "18728", "18730", "18738", "18739", "18744", "18745", "18747", "18748", "18749", "18750", "18751", "18752", "18753", "18755", "18757", "18758", "18759", "18761", "18762", "18764", "18765", "18766", "18767", "18768", "18769", "18770", "18771", "18772", "18775", "18776", "18777", "18780", "18781", "18784", "18787", "18788", "18789", "18791", "18793", "18795", "18797", "18800", "18802", "18804", "18805", "18806", "18808", "18811", "18813", "18816", "18818", "18819", "18821", "18822", "18823", "18824", "18830", "18834", "18835", "18837", "18838", "18839", "18841", "18843", "18845", "18846", "18848", "18849", "18850", "18851", "18858", "18862", "18863", "18864", "18870", "18874", "18875", "18880", "18883", "18884", "18887", "18889", "18890", "18892", "18893", "18894", "18895", "18897", "18898", "18900", "18901", "18902", "18907", "18908", "18909", "18910", "18911", "18917", "18919", "18926", "18929", "18930", "18931", "18934", "18935", "18936", "18937", "18939", "18940", "18943", "18945", "18948", "18950", "18951", "18952", "18955", "18956", "18958", "18959", "18961", "18963", "18964", "18966", "18968", "18969", "18970", "18971", "18973", "18975", "18977", "18979", "18981", "18982", "18983", "18984", "18986", "18987", "18988", "18989", "18990", "18991", "18992", "18994", "18996", "18999", "19000", "19002", "19004", "19005", "19007", "19010", "19012", "19014", "19017", "19024", "19025", "19028", "19029", "19031", "19032", "19035", "19037", "19038", "19039", "19041", "19042", "19043", "19048", "19049", "19050", "19051", "19052", "19053", "19056", "19057", "19058", "19064", "19065", "19068", "19070", "19074", "19076", "19078", "19080", "19081", "19086", "19087", "19088", "19089", "19090", "19091", "19092", "19093", "19094", "19095", "19096", "19098", "19099", "19100", "19103", "19104", "19106", "19109", "19112", "19115", "19117", "19120", "19121", "19123", "19127", "19128", "19129", "19130", "19131", "19134", "19137", "19140", "19143", "19145", "19146", "19147", "19149", "19155", "19156", "19160", "19164", "19166", "19169", "19172", "19176", "19178", "19179", "19183", "19184", "19185", "19186", "19188", "19189", "19192", "19195", "19196", "19197", "19198", "19199", "19200", "19201", "19202", "19207", "19209", "19210", "19213", "19214", "19217", "19218", "19221", "19226", "19227", "19228", "19232", "19235", "19237", "19240", "19242", "19251", "19252", "19254", "19256", "19258", "19260", "19261", "19262", "19264", "19266", "19272", "19273", "19274", "19275", "19276", "19278", "19279", "19281", "19283", "19285", "19288", "19290", "19291", "19296", "19299", "19300", "19301", "19302", "19305", "19306", "19308", "19309", "19319", "19320", "19321", "19323", "19328", "19330", "19331", "19333", "19336", "19337", "19339", "19343", "19344", "19345", "19350", "19351", "19354", "19355", "19357", "19358", "19362", "19363", "19369", "19372", "19373", "19377", "19378", "19381", "19383", "19386", "19388", "19390", "19391", "19392", "19393", "19394", "19397", "19399", "19401", "19402", "19404", "19405", "19406", "19407", "19408", "19410", "19413", "19415", "19417", "19420", "19424", "19426", "19436", "19442", "19447", "19448", "19449", "19451", "19455", "19456", "19457", "19458", "19459", "19460", "19462", "19463", "19464", "19465", "19466", "19469", "19470", "19471", "19472", "19474", "19476", "19478", "19479", "19481", "19482", "19484", "19485", "19486", "19487", "19491", "19493", "19494", "19495", "19500", "19505", "19506", "19507", "19509", "19512", "19513", "19516", "19518", "19519", "19520", "19523", "19525", "19526", "19530", "19532", "19533", "19534", "19535", "19538", "19539", "19541", "19542", "19543", "19546", "19547", "19549", "19550", "19551", "19552", "19559", "19560", "19562", "19564", "19566", "19569", "19570", "19572", "19573", "19574", "19577", "19579", "19580", "19582", "19583", "19584", "19585", "19589", "19590", "19593", "19594", "19595", "19597", "19602", "19605", "19606", "19609", "19610", "19611", "19615", "19616", "19617", "19619", "19620", "19621", "19622", "19625", "19626", "19627", "19628", "19629", "19630", "19632", "19633", "19637", "19641", "19644", "19646", "19647", "19650", "19651", "19655", "19660", "19661", "19663", "19665", "19667", "19668", "19669", "19674", "19677", "19678", "19679", "19684", "19686", "19691", "19692", "19695", "19696", "19697", "19698", "19699", "19700", "19702", "19706", "19708", "19709", "19712", "19714", "19724", "19725", "19727", "19731", "19732", "19735", "19738", "19739", "19743", "19746", "19747", "19749", "19754", "19759", "19761", "19762", "19767", "19778", "19779", "19780", "19783", "19784", "19786", "19787", "19791", "19792", "19793", "19794", "19798", "19799", "19800", "19802", "19804", "19810", "19813", "19814", "19816", "19817", "19819", "19820", "19822", "19823", "19824", "19825", "19826", "19827", "19828", "19829", "19832", "19833", "19834", "19835", "19836", "19837", "19841", "19843", "19844", "19845", "19846", "19853", "19856", "19857", "19861", "19862", "19865", "19866", "19867", "19869", "19870", "19872", "19874", "19876", "19877", "19881", "19883", "19885", "19886", "19887", "19888", "19889", "19891", "19894", "19903", "19904", "19909", "19910", "19912", "19913", "19914", "19920", "19924", "19925", "19927", "19929", "19931", "19932", "19934", "19937", "19938", "19940", "19942", "19943", "19945", "19949", "19953", "19954", "19955", "19958", "19959", "19960", "19962", "19965", "19966", "19968", "19970", "19974", "19980", "19981", "19990", "19992", "19996", "20000", "20002", "20004", "20007", "20008", "20012", "20016", "20020", "20021", "20022", "20028", "20031", "20035", "20038", "20040", "20041", "20043", "20047", "20049", "20051", "20052", "20053", "20054", "20057", "20058", "20060", "20061", "20062", "20067", "20069", "20075", "20078", "20082", "20086", "20087", "20088", "20090", "20092", "20094", "20098", "20099", "20100", "20101", "20103", "20104", "20105", "20106", "20107", "20108", "20110", "20111", "20116", "20117", "20120", "20122", "20129", "20132", "20133", "20134", "20135", "20136", "20138", "20139", "20140", "20144", "20146", "20147", "20148", "20149", "20150", "20151", "20154", "20157", "20162", "20165", "20166", "20170", "20172", "20176", "20177", "20178", "20179", "20180", "20181", "20184", "20187", "20188", "20189", "20190", "20191", "20195", "20197", "20198", "20202", "20203", "20205", "20206", "20207", "20208", "20210", "20211", "20219", "20221", "20225", "20227", "20228", "20229", "20231", "20235", "20236", "20245", "20248", "20249", "20251", "20252", "20255", "20257", "20259", "20260", "20261", "20264", "20265", "20266", "20269", "20270", "20272", "20276", "20277", "20278", "20280", "20283", "20285", "20288", "20289", "20291", "20293", "20295", "20296", "20298", "20300", "20302", "20304", "20306", "20307", "20308", "20311", "20312", "20313", "20314", "20316", "20319", "20320", "20327", "20328", "20329", "20331", "20332", "20335", "20336", "20337", "20339", "20340", "20342", "20344", "20345", "20346", "20348", "20349", "20350", "20351", "20353", "20354", "20355", "20356", "20359", "20362", "20364", "20366", "20368", "20369", "20370", "20371", "20373", "20374", "20375", "20376", "20377", "20378", "20379", "20384", "20386", "20387", "20388", "20390", "20391", "20392", "20393", "20395", "20398", "20400", "20401", "20402", "20403", "20404", "20406", "20408", "20411", "20413", "20414", "20415", "20419", "20420", "20422", "20423", "20425", "20426", "20427", "20430", "20432", "20433", "20435", "20440", "20443", "20445", "20449", "20450", "20454", "20455", "20458", "20459", "20461", "20463", "20464", "20467", "20468", "20470", "20474", "20477", "20478", "20481", "20483", "20484", "20485", "20486", "20487", "20488", "20489", "20490", "20492", "20498", "20502", "20504", "20505", "20506", "20513", "20516", "20518", "20520", "20521", "20522", "20523", "20524", "20525", "20526", "20529", "20530", "20531", "20534", "20537", "20539", "20541", "20542", "20543", "20544", "20550", "20553", "20555", "20557", "20559", "20560", "20561", "20562", "20563", "20564", "20566", "20568", "20569", "20573", "20578", "20579", "20580", "20581", "20583", "20584", "20585", "20589", "20591", "20595", "20596", "20597", "20598", "20600", "20601", "20602", "20604", "20607", "20610", "20612", "20613", "20614", "20615", "20618", "20620", "20624", "20626", "20627", "20628", "20629", "20631", "20633", "20635", "20636", "20640", "20642", "20644", "20645", "20649", "20654", "20656", "20657", "20659", "20660", "20662", "20663", "20664", "20666", "20668", "20671", "20672", "20673", "20675", "20679", "20683", "20684", "20685", "20686", "20688", "20689", "20690", "20691", "20694", "20695", "20696", "20702", "20704", "20706", "20710", "20712", "20713", "20714", "20715", "20719", "20721", "20725", "20726", "20727", "20728", "20729", "20730", "20731", "20732", "20735", "20738", "20739", "20740", "20741", "20742", "20747", "20748", "20749", "20751", "20754", "20760", "20762", "20763", "20768", "20769", "20771", "20777", "20782", "20786", "20787", "20788", "20790", "20795", "20796", "20799", "20801", "20803", "20805", "20806", "20811", "20813", "20814", "20815", "20817", "20821", "20822", "20824", "20830", "20831", "20838", "20839", "20845", "20846", "20847", "20849", "20851", "20852", "20855", "20856", "20857", "20858", "20859", "20860", "20863", "20864", "20867", "20868", "20870", "20873", "20874", "20878", "20879", "20888", "20889", "20890", "20892", "20893", "20894", "20897", "20898", "20899", "20900", "20902", "20907", "20913", "20917", "20919", "20922", "20925", "20927", "20932", "20933", "20935", "20940", "20942", "20943", "20944", "20945", "20946", "20948", "20949", "20951", "20954", "20957", "20959", "20960", "20961", "20965", "20967", "20969", "20972", "20973", "20974", "20975", "20976", "20977", "20978", "20980", "20981", "20983", "20984", "20989", "20992", "20994", "20996", "20998", "20999", "21002", "21003", "21004", "21005", "21006", "21007", "21008", "21009", "21015", "21017", "21018", "21021", "21022", "21023", "21024", "21026", "21027", "21028", "21029", "21030", "21032", "21034", "21038", "21039", "21040", "21042", "21043", "21048", "21049", "21053", "21056", "21057", "21058", "21059", "21060", "21064", "21068", "21069", "21071", "21072", "21073", "21075", "21077", "21078", "21084", "21086", "21088", "21089", "21095", "21098", "21100", "21101", "21104", "21106", "21110", "21111", "21113", "21114", "21116", "21121", "21122", "21123", "21128", "21130", "21133", "21136", "21137", "21139", "21140", "21141", "21142", "21144", "21146", "21148", "21149", "21150", "21151", "21157", "21160", "21161", "21166", "21167", "21168", "21169", "21170", "21171", "21173", "21175", "21178", "21179", "21181", "21184", "21187", "21188", "21189", "21190", "21193", "21194", "21195", "21198", "21200", "21202", "21204", "21205", "21206", "21207", "21208", "21211", "21212", "21216", "21217", "21218", "21221", "21223", "21224", "21227", "21231", "21232", "21234", "21236", "21240", "21241", "21244", "21245", "21246", "21248", "21250", "21253", "21254", "21255", "21256", "21257", "21258", "21260", "21264", "21268", "21269", "21270", "21274", "21279", "21280", "21281", "21283", "21284", "21297", "21299", "21301", "21304", "21305", "21308", "21309", "21310", "21311", "21312", "21313", "21314", "21315", "21316", "21321", "21324", "21325", "21326", "21327", "21329", "21330", "21331", "21336", "21337", "21338", "21339", "21342", "21343", "21345", "21347", "21350", "21351", "21352", "21353", "21354", "21358", "21359", "21360", "21361", "21363", "21364", "21368", "21371", "21373", "21374", "21376", "21382", "21383", "21385", "21386", "21387", "21388", "21391", "21394", "21397", "21398", "21399", "21401", "21404", "21406", "21410", "21413", "21414", "21423", "21425", "21427", "21431", "21435", "21436", "21441", "21443", "21444", "21445", "21446", "21448", "21451", "21454", "21456", "21458", "21461", "21462", "21463", "21465", "21467", "21468", "21469", "21473", "21475", "21476", "21477", "21479", "21480", "21483", "21486", "21487", "21488", "21489", "21493", "21496", "21503", "21504", "21509", "21513", "21518", "21519", "21520", "21521", "21525", "21526", "21528", "21530", "21531", "21533", "21535", "21536", "21540", "21542", "21544", "21546", "21549", "21550", "21553", "21554", "21556", "21561", "21563", "21564", "21565", "21566", "21567", "21570", "21571", "21572", "21575", "21576", "21577", "21578", "21579", "21580", "21582", "21583", "21590", "21592", "21593", "21594", "21597", "21598", "21604", "21606", "21607", "21611", "21612", "21613", "21616", "21618", "21619", "21621", "21622", "21623", "21626", "21629", "21630", "21631", "21632", "21633", "21634", "21636", "21637", "21638", "21639", "21640", "21641", "21642", "21643", "21646", "21649", "21650", "21651", "21652", "21656", "21657", "21658", "21659", "21663", "21664", "21668", "21673", "21682", "21683", "21685", "21686", "21687", "21689", "21693", "21694", "21695", "21696", "21697", "21699", "21700", "21701", "21702", "21703", "21704", "21706", "21709", "21710", "21711", "21715", "21718", "21719", "21720", "21722", "21723", "21727", "21728", "21729", "21730", "21732", "21733", "21734", "21735", "21736", "21740", "21742", "21745", "21747", "21750", "21751", "21752", "21753", "21758", "21759", "21760", "21764", "21765", "21766", "21771", "21773", "21774", "21778", "21781", "21782", "21783", "21788", "21794", "21799", "21800", "21802", "21803", "21805", "21807", "21810", "21811", "21813", "21814", "21815", "21820", "21822", "21828", "21829", "21832", "21834", "21835", "21836", "21838", "21840", "21842", "21844", "21847", "21848", "21849", "21850", "21851", "21852", "21854", "21857", "21859", "21860", "21862", "21864", "21865", "21866", "21868", "21869", "21870", "21873", "21876", "21877", "21879", "21880", "21883", "21884", "21885", "21887", "21888", "21892", "21893", "21895", "21898", "21899", "21902", "21905", "21908", "21909", "21911", "21913", "21914", "21915", "21916", "21919", "21920", "21921", "21922", "21926", "21927", "21928", "21933", "21934", "21938", "21939", "21941", "21942", "21944", "21947", "21948", "21949", "21951", "21952", "21953", "21954", "21956", "21958", "21963", "21964", "21969", "21972", "21977", "21978", "21979", "21985", "21986", "21987", "21991", "21996", "21997", "21999", "22000", "22001", "22006", "22009", "22010", "22013", "22014", "22017", "22018", "22020", "22023", "22024", "22026", "22028", "22029", "22030", "22033", "22036", "22037", "22038", "22041", "22042", "22044", "22046", "22048", "22050", "22052", "22054", "22058", "22060", "22062", "22063", "22067", "22070", "22071", "22073", "22074", "22075", "22077", "22078", "22080", "22081", "22086", "22087", "22090", "22091", "22093", "22098", "22100", "22101", "22102", "22103", "22105", "22106", "22107", "22111", "22112", "22113", "22116", "22117", "22119", "22121", "22122", "22123", "22124", "22125", "22130", "22132", "22134", "22138", "22140", "22141", "22142", "22143", "22144", "22145", "22147", "22149", "22151", "22153", "22158", "22160", "22161", "22163", "22164", "22166", "22169", "22170", "22172", "22174", "22175", "22178", "22179", "22180", "22183", "22184", "22186", "22187", "22192", "22196", "22197", "22199", "22200", "22201", "22202", "22203", "22205", "22206", "22209", "22213", "22215", "22217", "22218", "22219", "22220", "22222", "22223", "22224", "22225", "22226", "22229", "22230", "22233", "22234", "22235", "22236", "22238", "22239", "22240", "22241", "22243", "22245", "22247", "22248", "22249", "22251", "22255", "22256", "22258", "22261", "22266", "22268", "22271", "22273", "22281", "22284", "22286", "22287", "22288", "22289", "22290", "22294", "22295", "22297", "22299", "22300", "22303", "22304", "22305", "22307", "22310", "22313", "22318", "22320", "22323", "22324", "22326", "22329", "22331", "22332", "22333", "22334", "22336", "22338", "22340", "22342", "22345", "22348", "22349", "22350", "22352", "22354", "22355", "22356", "22357", "22358", "22359", "22360", "22362", "22366", "22370", "22371", "22372", "22373", "22377", "22380", "22381", "22384", "22385", "22388", "22389", "22392", "22396", "22397", "22398", "22399", "22400", "22401", "22402", "22403", "22406", "22408", "22409", "22410", "22411", "22412", "22414", "22416", "22420", "22421", "22422", "22423", "22425", "22427", "22428", "22429", "22430", "22431", "22432", "22433", "22437", "22438", "22446", "22447", "22448", "22450", "22454", "22455", "22457", "22461", "22464", "22468", "22471", "22473", "22476", "22477", "22478", "22481", "22483", "22487", "22490", "22493", "22494", "22496", "22497", "22498", "22504", "22507", "22508", "22510", "22512", "22513", "22515", "22516", "22520", "22521", "22522", "22524", "22527", "22530", "22532", "22533", "22534", "22535", "22539", "22540", "22542", "22543", "22545", "22547", "22548", "22549", "22552", "22553", "22554", "22556", "22557", "22559", "22562", "22563", "22564", "22566", "22567", "22571", "22575", "22576", "22578", "22580", "22583", "22584", "22586", "22590", "22592", "22596", "22600", "22601", "22605", "22606", "22607", "22610", "22613", "22616", "22618", "22619", "22620", "22621", "22622", "22623", "22626", "22630", "22634", "22635", "22636", "22637", "22640", "22642", "22643", "22645", "22646", "22648", "22649", "22652", "22657", "22658", "22659", "22661", "22664", "22671", "22674", "22675", "22676", "22678", "22683", "22684", "22685", "22691", "22692", "22695", "22698", "22700", "22702", "22703", "22705", "22708", "22710", "22711", "22712", "22713", "22715", "22716", "22718", "22719", "22721", "22722", "22723", "22724", "22725", "22727", "22730", "22732", "22734", "22735", "22736", "22737", "22738", "22739", "22740", "22741", "22743", "22744", "22746", "22749", "22750", "22753", "22754", "22755", "22756", "22757", "22760", "22761", "22762", "22763", "22767", "22768", "22769", "22770", "22772", "22776", "22778", "22779", "22781", "22784", "22785", "22786", "22788", "22791", "22793", "22794", "22795", "22796", "22797", "22798", "22799", "22801", "22804", "22806", "22807", "22808", "22811", "22812", "22813", "22814", "22816", "22817", "22819", "22822", "22823", "22829", "22834", "22836", "22837", "22839", "22841", "22845", "22846", "22849", "22850", "22851", "22852", "22853", "22859", "22860", "22861", "22862", "22864", "22865", "22866", "22868", "22870", "22871", "22881", "22882", "22883", "22884", "22885", "22889", "22893", "22894", "22895", "22899", "22901", "22902", "22903", "22904", "22905", "22906", "22907", "22912", "22914", "22916", "22920", "22921", "22922", "22923", "22927", "22929", "22934", "22935", "22936", "22937", "22938", "22940", "22944", "22946", "22948", "22950", "22951", "22955", "22956", "22959", "22961", "22963", "22965", "22966", "22970", "22971", "22972", "22974", "22977", "22978", "22979", "22981", "22982", "22985", "22986", "22988", "22991", "22995", "22996", "23000", "23002", "23003", "23004", "23008", "23009", "23010", "23012", "23013", "23014", "23016", "23019", "23020", "23021", "23022", "23023", "23024", "23025", "23027", "23028", "23030", "23031", "23032", "23033", "23034", "23035", "23036", "23040", "23041", "23043", "23046", "23049", "23050", "23051", "23055", "23056", "23060", "23061", "23063", "23066", "23067", "23068", "23069", "23071", "23073", "23076", "23077", "23081", "23083", "23084", "23085", "23086", "23087", "23090", "23091", "23093", "23096", "23097", "23099", "23104", "23109", "23112", "23114", "23115", "23116", "23118", "23119", "23121", "23123", "23124", "23125", "23126", "23128", "23129", "23130", "23133", "23135", "23136", "23137", "23138", "23139", "23140", "23143", "23144", "23145", "23148", "23152", "23153", "23156", "23158", "23159", "23160", "23161", "23162", "23163", "23170", "23175", "23176", "23177", "23178", "23180", "23182", "23184", "23187", "23189", "23190", "23191", "23199", "23205", "23206", "23209", "23212", "23213", "23214", "23215", "23219", "23221", "23222", "23223", "23224", "23225", "23229", "23230", "23234", "23235", "23236", "23238", "23240", "23241", "23243", "23245", "23246", "23248", "23250", "23254", "23256", "23258", "23259", "23260", "23262", "23263", "23265", "23270", "23271", "23275", "23276", "23277", "23278", "23281", "23282", "23285", "23286", "23287", "23288", "23289", "23290", "23292", "23293", "23294", "23297", "23298", "23302", "23303", "23304", "23305", "23307", "23309", "23310", "23312", "23313", "23314", "23315", "23325", "23328", "23331", "23334", "23335", "23337", "23338", "23339", "23341", "23342", "23346", "23349", "23353", "23356", "23357", "23360", "23361", "23364", "23365", "23366", "23367", "23368", "23370", "23376", "23377", "23378", "23379", "23380", "23381", "23386", "23388", "23390", "23392", "23395", "23398", "23399", "23401", "23402", "23404", "23406", "23407", "23414", "23415", "23416", "23420", "23421", "23422", "23423", "23425", "23427", "23429", "23430", "23433", "23434", "23436", "23437", "23442", "23444", "23445", "23448", "23451", "23454", "23456", "23459", "23460", "23462", "23464", "23467", "23469", "23472", "23473", "23482", "23483", "23484", "23485", "23486", "23488", "23491", "23492", "23494", "23495", "23496", "23497", "23498", "23501", "23502", "23504", "23507", "23508", "23509", "23513", "23517", "23520", "23522", "23524", "23525", "23528", "23530", "23533", "23535", "23537", "23538", "23539", "23541", "23543", "23545", "23546", "23547", "23548", "23549", "23550", "23552", "23554", "23556", "23558", "23559", "23560", "23561", "23563", "23564", "23565", "23566", "23567", "23570", "23571", "23572", "23577", "23579", "23580", "23582", "23583", "23584", "23585", "23589", "23591", "23592", "23593", "23594", "23595", "23596", "23603", "23605", "23607", "23609", "23610", "23612", "23614", "23615", "23616", "23617", "23618", "23619", "23621", "23623", "23626", "23627", "23628", "23629", "23630", "23631", "23633", "23635", "23636", "23637", "23639", "23640", "23641", "23642", "23643", "23645", "23646", "23648", "23650", "23652", "23653", "23654", "23655", "23657", "23658", "23661", "23662", "23663", "23665", "23666", "23670", "23673", "23674", "23677", "23678", "23679", "23680", "23681", "23682", "23683", "23686", "23688", "23689", "23693", "23696", "23697", "23699", "23700", "23704", "23705", "23709", "23710", "23713", "23717", "23718", "23720", "23721", "23729", "23733", "23738", "23739", "23740", "23742", "23743", "23744", "23745", "23746", "23747", "23749", "23754", "23755", "23758", "23759", "23761", "23765", "23770", "23771", "23772", "23773", "23774", "23777", "23779", "23782", "23784", "23786", "23790", "23793", "23794", "23799", "23801", "23805", "23808", "23809", "23812", "23813", "23815", "23817", "23818", "23819", "23820", "23821", "23825", "23828", "23830", "23833", "23834", "23836", "23837", "23838", "23842", "23846", "23848", "23855", "23856", "23858", "23859", "23861", "23862", "23863", "23864", "23867", "23870", "23873", "23878", "23881", "23883", "23884", "23885", "23887", "23893", "23895", "23897", "23898", "23899", "23905", "23906", "23907", "23908", "23909", "23910", "23911", "23913", "23914", "23922", "23925", "23927", "23928", "23932", "23934", "23935", "23941", "23942", "23944", "23945", "23946", "23949", "23950", "23952", "23954", "23959", "23961", "23963", "23964", "23966", "23967", "23968", "23973", "23976", "23978", "23983", "23984", "23985", "23987", "23988", "23989", "23990", "23993", "23994", "23996", "23997", "23998", "23999", "24001", "24002", "24005", "24007", "24008", "24009", "24010", "24012", "24013", "24014", "24015", "24017", "24018", "24019", "24020", "24023", "24025", "24029", "24031", "24033", "24034", "24036", "24039", "24040", "24041", "24042", "24043", "24045", "24047", "24048", "24052", "24056", "24057", "24058", "24062", "24065", "24066", "24068", "24070", "24071", "24073", "24074", "24076", "24080", "24081", "24083", "24085", "24088", "24089", "24090", "24092", "24093", "24094", "24095", "24096", "24097", "24098", "24103", "24109", "24115", "24120", "24123", "24124", "24126", "24129", "24130", "24131", "24133", "24136", "24138", "24140", "24141", "24142", "24143", "24144", "24146", "24149", "24151", "24155", "24157", "24161", "24162", "24163", "24165", "24167", "24168", "24169", "24170", "24175", "24177", "24181", "24184", "24186", "24187", "24189", "24194", "24195", "24197", "24200", "24201", "24202", "24203", "24207", "24209", "24210", "24212", "24213", "24215", "24217", "24218", "24220", "24222", "24223", "24224", "24225", "24226", "24227", "24228", "24229", "24232", "24233", "24236", "24237", "24238", "24239", "24241", "24244", "24245", "24247", "24250", "24251", "24253", "24257", "24259", "24261", "24262", "24263", "24265", "24266", "24269", "24272", "24273", "24274", "24279", "24280", "24284", "24285", "24292", "24294", "24296", "24297", "24299", "24302", "24303", "24304", "24308", "24311", "24315", "24316", "24317", "24319", "24323", "24324", "24325", "24326", "24328", "24329", "24332", "24336", "24337", "24338", "24339", "24340", "24347", "24348", "24351", "24356", "24358", "24359", "24360", "24361", "24364", "24370", "24379", "24381", "24382", "24384", "24385", "24388", "24389", "24393", "24394", "24395", "24396", "24397", "24399", "24403", "24405", "24406", "24410", "24412", "24414", "24415", "24419", "24420", "24421", "24423", "24424", "24426", "24427", "24429", "24431", "24435", "24439", "24440", "24442", "24444", "24445", "24450", "24452", "24454", "24455", "24457", "24458", "24459", "24461", "24467", "24471", "24472", "24474", "24475", "24476", "24479", "24481", "24482", "24484", "24487", "24494", "24497", "24498", "24503", "24504", "24505", "24507", "24508", "24509", "24511", "24512", "24518", "24520", "24521", "24522", "24523", "24524", "24525", "24526", "24527", "24530", "24532", "24536", "24538", "24539", "24540", "24541", "24542", "24543", "24544", "24545", "24547", "24548", "24549", "24550", "24551", "24556", "24557", "24559", "24560", "24563", "24564", "24565", "24566", "24567", "24568", "24570", "24573", "24577", "24578", "24579", "24580", "24581", "24584", "24586", "24588", "24590", "24595", "24598", "24600", "24602", "24603", "24604", "24607", "24609", "24610", "24612", "24620", "24621", "24623", "24624", "24625", "24627", "24629", "24630", "24632", "24633", "24634", "24636", "24639", "24641", "24642", "24644", "24646", "24647", "24649", "24656", "24657", "24660", "24663", "24664", "24667", "24671", "24672", "24673", "24675", "24676", "24677", "24678", "24679", "24680", "24682", "24684", "24685", "24686", "24688", "24690", "24694", "24696", "24698", "24699", "24700", "24702", "24703", "24706", "24707", "24708", "24709", "24712", "24716", "24717", "24719", "24720", "24721", "24723", "24724", "24726", "24729", "24731", "24733", "24734", "24735", "24737", "24738", "24742", "24743", "24752", "24754", "24755", "24757", "24758", "24759", "24760", "24761", "24765", "24767", "24771", "24772", "24773", "24774", "24775", "24776", "24777", "24782", "24786", "24788", "24789", "24790", "24791", "24792", "24793", "24794", "24795", "24796", "24797", "24798", "24800", "24801", "24802", "24803", "24804", "24807", "24811", "24813", "24815", "24816", "24818", "24822", "24823", "24825", "24826", "24831", "24833", "24834", "24836", "24837", "24839", "24841", "24842", "24845", "24846", "24848", "24849", "24852", "24857", "24858", "24859", "24861", "24864", "24868", "24869", "24873", "24876", "24877", "24881", "24883", "24884", "24887", "24893", "24894", "24902", "24908", "24910", "24913", "24914", "24915", "24916", "24921", "24922", "24925", "24926", "24927", "24928", "24929", "24931", "24935", "24936", "24937", "24940", "24945", "24947", "24949", "24951", "24952", "24954", "24958", "24959", "24963", "24964", "24966", "24967", "24968", "24972", "24973", "24977", "24978", "24981", "24985", "24988", "24992", "24993", "24994", "24995", "24996", "24997", "24998", "25000", "25001", "25002", "25003", "25006", "25007", "25009", "25011", "25013", "25014", "25015", "25018", "25019", "25020", "25021", "25022", "25023", "25025", "25026", "25029", "25030", "25032", "25035", "25036", "25038", "25039", "25041", "25043", "25045", "25049", "25050", "25051", "25052", "25053", "25056", "25060", "25061", "25062", "25063", "25064", "25065", "25068", "25072", "25073", "25074", "25075", "25076", "25077", "25083", "25084", "25085", "25087", "25088", "25091", "25092", "25095", "25097", "25098", "25099", "25100", "25101", "25103", "25106", "25107", "25109", "25110", "25115", "25117", "25119", "25120", "25123", "25125", "25127", "25132", "25134", "25135", "25136", "25137", "25140", "25141", "25145", "25146", "25147", "25149", "25150", "25155", "25156", "25157", "25161", "25165", "25167", "25169", "25174", "25175", "25177", "25180", "25182", "25184", "25185", "25186", "25189", "25191", "25192", "25193", "25196", "25200", "25202", "25204", "25206", "25213", "25214", "25215", "25217", "25218", "25219", "25220", "25221", "25222", "25225", "25226", "25228", "25229", "25230", "25232", "25233", "25234", "25235", "25236", "25238", "25245", "25246", "25247", "25250", "25251", "25252", "25253", "25254", "25255", "25257", "25260", "25261", "25263", "25264", "25266", "25267", "25269", "25271", "25272", "25273", "25275", "25279", "25280", "25281", "25283", "25285", "25286", "25287", "25289", "25291", "25294", "25295", "25296", "25297", "25298", "25300", "25301", "25304", "25308", "25309", "25311", "25312", "25313", "25314", "25315", "25316", "25320", "25321", "25322", "25324", "25325", "25326", "25327", "25328", "25329", "25330", "25331", "25333", "25334", "25335", "25336", "25341", "25343", "25344", "25345", "25346", "25347", "25348", "25349", "25350", "25351", "25352", "25353", "25355", "25356", "25357", "25361", "25362", "25363", "25366", "25372", "25373", "25374", "25375", "25379", "25381", "25383", "25384", "25385", "25392", "25394", "25395", "25397", "25398", "25399", "25400", "25404", "25405", "25406", "25407", "25408", "25409", "25410", "25412", "25414", "25416", "25418", "25420", "25426", "25427", "25430", "25431", "25434", "25436", "25440", "25441", "25442", "25443", "25445", "25446", "25447", "25449", "25450", "25453", "25454", "25455", "25458", "25459", "25461", "25462", "25464", "25465", "25467", "25468", "25471", "25472", "25473", "25474", "25475", "25476", "25477", "25479", "25480", "25486", "25490", "25491", "25492", "25493", "25494", "25495", "25496", "25497", "25499", "25503", "25507", "25512", "25513", "25514", "25515", "25520", "25522", "25524", "25529", "25530", "25534", "25539", "25544", "25545", "25546", "25548", "25554", "25555", "25556", "25557", "25563", "25564", "25566", "25567", "25568", "25569", "25570", "25571", "25572", "25574", "25575", "25576", "25579", "25582", "25584", "25585", "25586", "25593", "25594", "25597", "25599", "25601", "25602", "25604", "25605", "25606", "25608", "25611", "25613", "25614", "25618", "25619", "25620", "25621", "25622", "25623", "25624", "25625", "25627", "25629", "25630", "25631", "25632", "25635", "25638", "25642", "25643", "25644", "25652", "25656", "25657", "25659", "25661", "25663", "25664", "25665", "25668", "25670", "25672", "25677", "25678", "25680", "25681", "25684", "25687", "25688", "25691", "25693", "25694", "25696", "25697", "25702", "25704", "25705", "25707", "25712", "25714", "25715", "25717", "25719", "25722", "25723", "25726", "25728", "25729", "25731", "25733", "25735", "25737", "25740", "25741", "25742", "25743", "25744", "25745", "25747", "25750", "25751", "25753", "25755", "25756", "25757", "25758", "25759", "25761", "25764", "25769", "25770", "25771", "25772", "25773", "25775", "25776", "25777", "25779", "25783", "25786", "25789", "25790", "25794", "25798", "25799", "25801", "25804", "25807", "25809", "25811", "25816", "25817", "25818", "25819", "25823", "25824", "25826", "25827", "25828", "25829", "25830", "25831", "25832", "25834", "25835", "25836", "25838", "25842", "25844", "25845", "25846", "25847", "25848", "25849", "25850", "25851", "25852", "25853", "25855", "25857", "25858", "25859", "25861", "25863", "25864", "25869", "25870", "25872", "25874", "25876", "25877", "25879", "25880", "25882", "25885", "25888", "25889", "25890", "25894", "25895", "25896", "25897", "25898", "25899", "25903", "25904", "25905", "25906", "25907", "25910", "25911", "25916", "25917", "25923", "25924", "25926", "25928", "25929", "25930", "25931", "25932", "25938", "25939", "25941", "25942", "25943", "25944", "25945", "25946", "25947", "25948", "25949", "25952", "25954", "25955", "25957", "25958", "25961", "25963", "25967", "25970", "25974", "25975", "25977", "25978", "25980", "25982", "25983", "25984", "25986", "25987", "25989", "25992", "25996", "25998", "25999", "26001", "26002", "26004", "26005", "26006", "26008", "26009", "26010", "26011", "26012", "26015", "26016", "26017", "26018", "26020", "26022", "26025", "26026", "26031", "26033", "26035", "26036", "26041", "26042", "26044", "26046", "26047", "26048", "26049", "26050", "26051", "26053", "26054", "26055", "26056", "26057", "26060", "26061", "26062", "26063", "26066", "26072", "26073", "26078", "26081", "26088", "26093", "26095", "26096", "26097", "26098", "26099", "26103", "26104", "26106", "26108", "26110", "26112", "26113", "26114", "26116", "26118", "26119", "26124", "26125", "26128", "26129", "26130", "26131", "26132", "26133", "26134", "26135", "26137", "26138", "26139", "26140", "26141", "26144", "26145", "26147", "26149", "26153", "26154", "26156", "26158", "26159", "26161", "26163", "26166", "26167", "26171", "26175", "26176", "26178", "26179", "26180", "26182", "26184", "26185", "26187", "26188", "26189", "26190", "26193", "26195", "26198", "26199", "26200", "26203", "26210", "26213", "26214", "26215", "26220", "26222", "26226", "26228", "26229", "26231", "26233", "26234", "26237", "26238", "26239", "26240", "26248", "26249", "26250", "26251", "26252", "26254", "26265", "26267", "26268", "26269", "26270", "26273", "26276", "26277", "26281", "26282", "26283", "26286", "26287", "26289", "26290", "26292", "26293", "26294", "26300", "26301", "26305", "26308", "26309", "26310", "26311", "26314", "26317", "26318", "26321", "26323", "26324", "26325", "26327", "26328", "26329", "26330", "26334", "26337", "26338", "26343", "26347", "26349", "26350", "26351", "26354", "26356", "26358", "26361", "26362", "26363", "26364", "26368", "26370", "26372", "26373", "26374", "26377", "26379", "26386", "26392", "26393", "26394", "26395", "26396", "26398", "26399", "26401", "26403", "26405", "26406", "26407", "26408", "26409", "26412", "26413", "26415", "26416", "26417", "26418", "26419", "26424", "26426", "26427", "26429", "26430", "26431", "26432", "26433", "26434", "26435", "26437", "26440", "26441", "26442", "26443", "26444", "26447", "26450", "26451", "26452", "26453", "26456", "26458", "26460", "26462", "26463", "26464", "26470", "26472", "26473", "26475", "26476", "26477", "26479", "26480", "26483", "26484", "26487", "26488", "26489", "26495", "26497", "26498", "26499", "26500", "26502", "26503", "26504", "26505", "26506", "26508", "26509", "26510", "26512", "26514", "26515", "26516", "26520", "26521", "26522", "26523", "26524", "26525", "26526", "26530", "26531", "26533", "26537", "26538", "26540", "26541", "26543", "26546", "26549", "26550", "26552", "26560", "26561", "26564", "26565", "26567", "26569", "26571", "26573", "26576", "26577", "26578", "26580", "26582", "26590", "26591", "26593", "26594", "26595", "26596", "26597", "26599", "26600", "26604", "26605", "26607", "26608", "26609", "26610", "26612", "26613", "26614", "26617", "26618", "26620", "26621", "26623", "26625", "26626", "26628", "26633", "26634", "26635", "26639", "26640", "26642", "26644", "26645", "26646", "26649", "26653", "26654", "26657", "26659", "26661", "26662", "26664", "26668", "26670", "26672", "26673", "26676", "26677", "26678", "26681", "26682", "26684", "26685", "26686", "26687", "26688", "26690", "26698", "26701", "26702", "26703", "26705", "26707", "26708", "26709", "26712", "26718", "26719", "26720", "26723", "26724", "26726", "26729", "26732", "26733", "26737", "26739", "26742", "26744", "26745", "26747", "26748", "26751", "26753", "26755", "26756", "26757", "26766", "26769", "26775", "26777", "26780", "26786", "26787", "26794", "26796", "26797", "26798", "26799", "26800", "26803", "26806", "26808", "26809", "26811", "26812", "26821", "26822", "26824", "26826", "26830", "26831", "26832", "26835", "26839", "26840", "26841", "26843", "26844", "26846", "26856", "26858", "26859", "26861", "26866", "26867", "26868", "26871", "26874", "26875", "26879", "26880", "26883", "26884", "26888", "26890", "26893", "26896", "26898", "26899", "26901", "26903", "26904", "26905", "26906", "26907", "26908", "26909", "26910", "26911", "26912", "26913", "26916", "26917", "26920", "26921", "26922", "26923", "26924", "26928", "26931", "26932", "26935", "26936", "26938", "26939", "26940", "26941", "26942", "26943", "26944", "26953", "26956", "26960", "26962", "26965", "26966", "26967", "26969", "26973", "26974", "26975", "26979", "26986", "26987", "26988", "26995", "26997", "26998", "27006", "27007", "27010", "27011", "27012", "27015", "27020", "27021", "27022", "27026", "27027", "27030", "27031", "27033", "27034", "27041", "27043", "27044", "27045", "27046", "27053", "27059", "27060", "27061", "27062", "27067", "27070", "27072", "27073", "27075", "27076", "27078", "27081", "27083", "27086", "27091", "27093", "27095", "27096", "27099", "27104", "27105", "27106", "27107", "27109", "27110", "27114", "27116", "27119", "27121", "27123", "27127", "27129", "27130", "27131", "27135", "27136", "27137", "27138", "27140", "27142", "27143", "27144", "27145", "27148", "27149", "27151", "27153", "27155", "27157", "27160", "27161", "27162", "27166", "27167", "27169", "27170", "27174", "27175", "27177", "27178", "27179", "27180", "27182", "27183", "27184", "27185", "27186", "27189", "27193", "27200", "27201", "27203", "27205", "27211", "27212", "27214", "27216", "27219", "27220", "27224", "27225", "27227", "27228", "27229", "27232", "27234", "27235", "27238", "27244", "27248", "27251", "27252", "27255", "27256", "27260", "27261", "27262", "27264", "27266", "27267", "27268", "27271", "27272", "27273", "27276", "27277", "27280", "27283", "27284", "27285", "27286", "27287", "27288", "27291", "27295", "27297", "27300", "27301", "27305", "27307", "27309", "27311", "27312", "27313", "27316", "27318", "27320", "27322", "27324", "27326", "27327", "27328", "27329", "27331", "27332", "27333", "27334", "27336", "27337", "27338", "27339", "27341", "27346", "27348", "27352", "27353", "27354", "27355", "27356", "27359", "27361", "27363", "27364", "27365", "27366", "27367", "27368", "27370", "27372", "27373", "27374", "27379", "27383", "27384", "27385", "27388", "27392", "27393", "27394", "27399", "27401", "27403", "27404", "27406", "27407", "27408", "27412", "27413", "27414", "27415", "27417", "27418", "27420", "27422", "27423", "27424", "27433", "27435", "27437", "27438", "27439", "27441", "27442", "27446", "27448", "27449", "27450", "27451", "27455", "27456", "27458", "27462", "27464", "27465", "27466", "27467", "27468", "27469", "27471", "27475", "27477", "27479", "27480", "27484", "27485", "27490", "27493", "27494", "27498", "27499", "27500", "27504", "27505", "27509", "27513", "27516", "27522", "27523", "27524", "27525", "27527", "27531", "27532", "27533", "27535", "27538", "27541", "27546", "27548", "27550", "27552", "27555", "27558", "27559", "27564", "27567", "27573", "27577", "27580", "27582", "27583", "27585", "27586", "27587", "27589", "27591", "27592", "27594", "27595", "27599", "27603", "27604", "27606", "27610", "27611", "27612", "27613", "27614", "27616", "27617", "27620", "27621", "27622", "27625", "27629", "27631", "27632", "27633", "27638", "27639", "27641", "27642", "27645", "27647", "27649", "27654", "27655", "27656", "27658", "27660", "27662", "27665", "27668", "27669", "27672", "27673", "27675", "27677", "27679", "27681", "27682", "27683", "27689", "27691", "27694", "27695", "27696", "27699", "27700", "27702", "27704", "27706", "27707", "27708", "27709", "27712", "27713", "27715", "27719", "27726", "27728", "27732", "27733", "27735", "27737", "27738", "27739", "27740", "27744", "27747", "27748", "27750", "27752", "27753", "27754", "27758", "27759", "27761", "27763", "27765", "27766", "27767", "27768", "27769", "27770", "27772", "27778", "27781", "27784", "27788", "27790", "27792", "27793", "27795", "27797", "27799", "27801", "27804", "27805", "27806", "27807", "27811", "27812", "27813", "27814", "27815", "27817", "27819", "27820", "27824", "27827", "27829", "27830", "27832", "27833", "27836", "27837", "27840", "27843", "27845", "27848", "27850", "27853", "27856", "27858", "27859", "27860", "27861", "27862", "27865", "27871", "27874", "27875", "27877", "27880", "27883", "27884", "27888", "27889", "27890", "27891", "27892", "27893", "27895", "27896", "27898", "27902", "27904", "27908", "27910", "27912", "27914", "27915", "27917", "27919", "27922", "27924", "27925", "27926", "27928", "27932", "27933", "27935", "27937", "27938", "27939", "27940", "27941", "27942", "27945", "27949", "27952", "27953", "27954", "27955", "27956", "27958", "27963", "27964", "27966", "27967", "27968", "27970", "27971", "27972", "27977", "27978", "27980", "27982", "27983", "27984", "27986", "27987", "27988", "27989", "27990", "27991", "27992", "27993", "27996", "27997", "27998", "28000", "28001", "28003", "28014", "28015", "28019", "28021", "28022", "28023", "28027", "28033", "28034", "28036", "28037", "28038", "28040", "28042", "28045", "28046", "28047", "28049", "28052", "28054", "28056", "28059", "28060", "28061", "28062", "28064", "28065", "28066", "28068", "28069", "28070", "28071", "28073", "28077", "28079", "28081", "28084", "28085", "28088", "28089", "28090", "28091", "28092", "28093", "28095", "28098", "28099", "28102", "28103", "28104", "28105", "28108", "28113", "28114", "28116", "28118", "28120", "28121", "28122", "28123", "28125", "28128", "28131", "28135", "28136", "28138", "28139", "28142", "28143", "28145", "28146", "28150", "28152", "28153", "28160", "28161", "28162", "28163", "28164", "28165", "28169", "28171", "28174", "28177", "28179", "28181", "28185", "28187", "28188", "28191", "28193", "28195", "28196", "28198", "28199", "28201", "28203", "28207", "28208", "28209", "28211", "28212", "28214", "28216", "28218", "28220", "28224", "28227", "28230", "28234", "28236", "28237", "28240", "28243", "28245", "28246", "28248", "28251", "28252", "28254", "28256", "28258", "28259", "28260", "28263", "28264", "28265", "28267", "28272", "28276", "28279", "28280", "28284", "28286", "28287", "28288", "28289", "28295", "28296", "28297", "28298", "28300", "28303", "28307", "28308", "28309", "28310", "28312", "28313", "28314", "28315", "28316", "28317", "28318", "28320", "28325", "28327", "28328", "28330", "28331", "28333", "28335", "28336", "28337", "28338", "28339", "28341", "28343", "28344", "28345", "28349", "28352", "28354", "28355", "28359", "28362", "28364", "28367", "28369", "28370", "28372", "28373", "28375", "28376", "28379", "28380", "28382", "28383", "28384", "28387", "28388", "28389", "28394", "28395", "28396", "28399", "28400", "28403", "28405", "28406", "28412", "28413", "28420", "28421", "28423", "28424", "28427", "28429", "28430", "28431", "28438", "28440", "28441", "28442", "28443", "28445", "28447", "28452", "28453", "28455", "28456", "28460", "28465", "28467", "28468", "28471", "28474", "28475", "28478", "28482", "28484", "28486", "28488", "28490", "28491", "28494", "28495", "28496", "28499", "28503", "28504", "28506", "28507", "28511", "28516", "28517", "28519", "28520", "28521", "28522", "28523", "28524", "28525", "28526", "28527", "28530", "28531", "28532", "28535", "28538", "28540", "28543", "28545", "28546", "28551", "28553", "28555", "28556", "28559", "28563", "28565", "28566", "28567", "28570", "28571", "28572", "28574", "28576", "28578", "28579", "28580", "28581", "28583", "28585", "28586", "28587", "28589", "28590", "28591", "28592", "28593", "28594", "28595", "28596", "28597", "28598", "28599", "28605", "28606", "28609", "28610", "28611", "28614", "28615", "28616", "28618", "28619", "28620", "28622", "28624", "28626", "28628", "28629", "28633", "28634", "28635", "28639", "28640", "28642", "28644", "28645", "28648", "28649", "28652", "28653", "28654", "28655", "28657", "28658", "28664", "28667", "28670", "28671", "28672", "28674", "28676", "28677", "28678", "28679", "28680", "28682", "28686", "28687", "28688", "28691", "28694", "28695", "28696", "28697", "28699", "28701", "28703", "28706", "28712", "28717", "28718", "28719", "28722", "28723", "28725", "28729", "28730", "28735", "28737", "28738", "28740", "28741", "28743", "28745", "28747", "28748", "28749", "28751", "28752", "28753", "28754", "28756", "28757", "28761", "28763", "28765", "28766", "28767", "28769", "28772", "28773", "28774", "28776", "28779", "28780", "28781", "28783", "28785", "28789", "28790", "28792", "28794", "28795", "28797", "28803", "28804", "28806", "28808", "28812", "28813", "28814", "28815", "28817", "28818", "28820", "28823", "28824", "28825", "28826", "28827", "28828", "28829", "28830", "28831", "28832", "28836", "28837", "28838", "28840", "28841", "28842", "28844", "28847", "28851", "28852", "28853", "28854", "28855", "28857", "28859", "28861", "28862", "28863", "28864", "28865", "28869", "28870", "28871", "28872", "28873", "28874", "28876", "28880", "28886", "28887", "28889", "28890", "28891", "28893", "28896", "28899", "28902", "28903", "28905", "28906", "28907", "28908", "28913", "28914", "28916", "28917", "28920", "28921", "28922", "28924", "28925", "28926", "28928", "28929", "28931", "28932", "28938", "28941", "28942", "28943", "28944", "28945", "28946", "28947", "28949", "28951", "28952", "28953", "28954", "28955", "28956", "28957", "28958", "28962", "28964", "28965", "28966", "28967", "28968", "28969", "28971", "28973", "28975", "28976", "28977", "28978", "28981", "28984", "28985", "28986", "28987", "28989", "28990", "28991", "28994", "28995", "28996", "28997", "28998", "29000", "29001", "29002", "29003", "29005", "29008", "29012", "29014", "29015", "29017", "29019", "29021", "29022", "29023", "29024", "29025", "29031", "29032", "29034", "29040", "29041", "29042", "29045", "29047", "29048", "29050", "29051", "29057", "29058", "29059", "29060", "29062", "29063", "29065", "29066", "29067", "29069", "29070", "29072", "29073", "29075", "29076", "29078", "29079", "29080", "29089", "29092", "29093", "29094", "29095", "29099", "29101", "29103", "29105", "29106", "29108", "29110", "29112", "29113", "29121", "29122", "29123", "29124", "29125", "29128", "29129", "29130", "29131", "29132", "29133", "29134", "29136", "29138", "29140", "29143", "29144", "29145", "29146", "29147", "29148", "29149", "29150", "29153", "29156", "29157", "29160", "29163", "29164", "29165", "29167", "29170", "29171", "29173", "29174", "29176", "29177", "29178", "29180", "29181", "29183", "29184", "29186", "29188", "29193", "29194", "29197", "29202", "29203", "29205", "29206", "29208", "29209", "29211", "29212", "29214", "29217", "29218", "29219", "29220", "29221", "29225", "29233", "29235", "29236", "29237", "29238", "29240", "29241", "29242", "29244", "29246", "29248", "29250", "29251", "29252", "29253", "29254", "29255", "29257", "29260", "29261", "29263", "29264", "29267", "29271", "29274", "29278", "29279", "29281", "29282", "29286", "29287", "29292", "29293", "29294", "29295", "29296", "29305", "29306", "29307", "29308", "29310", "29311", "29312", "29313", "29314", "29315", "29316", "29317", "29319", "29323", "29324", "29326", "29327", "29330", "29331", "29335", "29340", "29341", "29343", "29344", "29346", "29347", "29348", "29349", "29352", "29353", "29355", "29357", "29359", "29361", "29362", "29363", "29364", "29365", "29367", "29368", "29371", "29372", "29373", "29374", "29377", "29380", "29381", "29382", "29386", "29387", "29389", "29390", "29391", "29395", "29396", "29398", "29399", "29403", "29405", "29406", "29407", "29409", "29411", "29417", "29418", "29419", "29420", "29421", "29422", "29424", "29426", "29429", "29434", "29436", "29437", "29438", "29439", "29444", "29447", "29448", "29449", "29450", "29451", "29453", "29456", "29457", "29458", "29461", "29464", "29468", "29469", "29471", "29476", "29481", "29483", "29484", "29486", "29487", "29488", "29489", "29492", "29494", "29496", "29499", "29500", "29502", "29503", "29504", "29508", "29510", "29514", "29518", "29523", "29524", "29527", "29528", "29530", "29533", "29534", "29535", "29536", "29539", "29540", "29541", "29544", "29545", "29546", "29547", "29552", "29554", "29556", "29557", "29560", "29561", "29563", "29568", "29569", "29571", "29572", "29576", "29578", "29583", "29585", "29588", "29590", "29593", "29595", "29596", "29598", "29600", "29602", "29607", "29609", "29610", "29614", "29617", "29622", "29623", "29624", "29625", "29627", "29629", "29630", "29631", "29633", "29634", "29635", "29638", "29644", "29645", "29646", "29647", "29651", "29652", "29656", "29658", "29659", "29665", "29666", "29667", "29668", "29669", "29671", "29672", "29674", "29675", "29676", "29679", "29682", "29683", "29688", "29690", "29691", "29693", "29694", "29698", "29701", "29704", "29708", "29709", "29710", "29712", "29713", "29714", "29716", "29718", "29720", "29721", "29723", "29724", "29729", "29734", "29736", "29738", "29739", "29740", "29742", "29744", "29750", "29751", "29755", "29756", "29759", "29761", "29763", "29764", "29765", "29767", "29769", "29771", "29772", "29774", "29776", "29777", "29780", "29783", "29784", "29785", "29786", "29788", "29789", "29790", "29791", "29794", "29797", "29805", "29806", "29808", "29809", "29811", "29812", "29814", "29815", "29825", "29826", "29827", "29831", "29833", "29837", "29839", "29845", "29846", "29847", "29848", "29849", "29850", "29852", "29854", "29855", "29856", "29863", "29864", "29867", "29869", "29870", "29875", "29877", "29878", "29879", "29880", "29881", "29883", "29885", "29886", "29887", "29890", "29893", "29897", "29898", "29899", "29903", "29906", "29911", "29912", "29914", "29919", "29921", "29922", "29923", "29925", "29928", "29929", "29930", "29931", "29934", "29938", "29940", "29941", "29942", "29944", "29946", "29947", "29949", "29956", "29958", "29959", "29962", "29963", "29969", "29970", "29971", "29973", "29975", "29978", "29982", "29983", "29984", "29986", "29990", "29991", "29992", "29996", "29999", "30001", "30002", "30006", "30008", "30010", "30011", "30016", "30017", "30022", "30024", "30027", "30035", "30040", "30043", "30044", "30045", "30047", "30049", "30053", "30056", "30057", "30059", "30062", "30063", "30065", "30067", "30069", "30070", "30071", "30072", "30073", "30074", "30076", "30077", "30078", "30079", "30080", "30081", "30083", "30085", "30086", "30093", "30098", "30099", "30102", "30103", "30104", "30106", "30107", "30108", "30110", "30116", "30117", "30118", "30120", "30122", "30124", "30125", "30128", "30129", "30130", "30131", "30132", "30134", "30136", "30140", "30142", "30144", "30145", "30148", "30149", "30150", "30152", "30153", "30154", "30155", "30156", "30158", "30159", "30160", "30162", "30163", "30165", "30166", "30167", "30168", "30169", "30170", "30171", "30172", "30173", "30175", "30177", "30179", "30180", "30182", "30184", "30185", "30187", "30189", "30194", "30195", "30196", "30198", "30199", "30201", "30203", "30204", "30206", "30208", "30209", "30210", "30211", "30213", "30214", "30215", "30218", "30219", "30220", "30221", "30232", "30233", "30234", "30235", "30236", "30238", "30239", "30242", "30244", "30246", "30247", "30249", "30253", "30258", "30259", "30260", "30261", "30263", "30266", "30267", "30269", "30270", "30271", "30272", "30274", "30275", "30277", "30280", "30281", "30285", "30287", "30289", "30294", "30295", "30299", "30303", "30307", "30310", "30311", "30313", "30314", "30316", "30318", "30321", "30324", "30325", "30326", "30327", "30328", "30329", "30331", "30334", "30335", "30336", "30338", "30340", "30341", "30343", "30345", "30346", "30347", "30351", "30352", "30353", "30356", "30360", "30362", "30364", "30365", "30366", "30367", "30368", "30369", "30370", "30372", "30373", "30374", "30376", "30378", "30381", "30382", "30386", "30388", "30390", "30397", "30398", "30399", "30400", "30401", "30402", "30403", "30406", "30410", "30414", "30417", "30419", "30422", "30425", "30430", "30434", "30435", "30437", "30439", "30440", "30441", "30442", "30443", "30445", "30446", "30447", "30448", "30449", "30451", "30452", "30453", "30455", "30456", "30457", "30458", "30460", "30461", "30462", "30463", "30464", "30465", "30470", "30473", "30475", "30476", "30478", "30479", "30480", "30484", "30485", "30488", "30492", "30493", "30496", "30497", "30501", "30504", "30505", "30507", "30511", "30512", "30513", "30514", "30516", "30518", "30519", "30521", "30523", "30527", "30530", "30531", "30533", "30534", "30537", "30538", "30541", "30543", "30544", "30547", "30548", "30549", "30550", "30551", "30554", "30555", "30557", "30561", "30562", "30563", "30566", "30569", "30571", "30575", "30576", "30577", "30581", "30583", "30586", "30588", "30589", "30590", "30591", "30592", "30593", "30594", "30599", "30602", "30603", "30604", "30606", "30608", "30609", "30610", "30612", "30614", "30616", "30619", "30621", "30624", "30625", "30626", "30628", "30630", "30634", "30636", "30637", "30639", "30642", "30643", "30644", "30645", "30648", "30649", "30654", "30655", "30658", "30659", "30660", "30661", "30667", "30669", "30670", "30672", "30675", "30676", "30677", "30678", "30679", "30680", "30682", "30683", "30685", "30687", "30688", "30690", "30694", "30697", "30701", "30704", "30708", "30709", "30710", "30711", "30716", "30717", "30719", "30720", "30723", "30724", "30730", "30734", "30737", "30739", "30740", "30741", "30742", "30745", "30747", "30749", "30750", "30752", "30753", "30755", "30756", "30758", "30759", "30760", "30765", "30766", "30771", "30772", "30774", "30775", "30776", "30778", "30781", "30782", "30784", "30785", "30786", "30787", "30789", "30791", "30792", "30793", "30795", "30799", "30800", "30804", "30805", "30806", "30807", "30808", "30809", "30813", "30818", "30820", "30821", "30825", "30827", "30828", "30829", "30830", "30837", "30838", "30839", "30844", "30845", "30847", "30848", "30851", "30857", "30860", "30861", "30862", "30870", "30873", "30875", "30876", "30878", "30879", "30880", "30885", "30886", "30887", "30888", "30889", "30890", "30891", "30892", "30893", "30894", "30895", "30904", "30905", "30906", "30908", "30910", "30913", "30916", "30917", "30920", "30923", "30924", "30925", "30926", "30929", "30931", "30932", "30933", "30934", "30935", "30936", "30937", "30939", "30940", "30941", "30944", "30945", "30952", "30953", "30956", "30961", "30962", "30967", "30968", "30970", "30971", "30972", "30973", "30975", "30977", "30978", "30980", "30984", "30987", "30992", "30993", "30994", "31000", "31001", "31002", "31004", "31006", "31007", "31010", "31012", "31014", "31016", "31020", "31026", "31028", "31029", "31031", "31032", "31036", "31038", "31045", "31047", "31049", "31051", "31052", "31053", "31058", "31059", "31062", "31063", "31064", "31066", "31073", "31074", "31079", "31080", "31081", "31083", "31086", "31089", "31091", "31092", "31093", "31094", "31095", "31096", "31098", "31099", "31101", "31102", "31103", "31105", "31106", "31108", "31109", "31114", "31115", "31119", "31121", "31122", "31126", "31127", "31129", "31131", "31133", "31135", "31137", "31139", "31141", "31142", "31144", "31145", "31149", "31151", "31153", "31157", "31159", "31160", "31161", "31164", "31166", "31167", "31170", "31172", "31175", "31177", "31181", "31182", "31184", "31187", "31188", "31189", "31190", "31192", "31194", "31197", "31198", "31199", "31200", "31201", "31202", "31203", "31204", "31205", "31206", "31210", "31211", "31212", "31213", "31214", "31215", "31218", "31219", "31222", "31223", "31226", "31230", "31231", "31232", "31235", "31236", "31239", "31241", "31242", "31243", "31249", "31250", "31253", "31258", "31259", "31262", "31266", "31269", "31270", "31273", "31276", "31279", "31280", "31282", "31283", "31285", "31286", "31288", "31289", "31294", "31296", "31297", "31299", "31302", "31304", "31306", "31309", "31310", "31311", "31314", "31315", "31318", "31319", "31321", "31324", "31325", "31326", "31328", "31333", "31336", "31337", "31338", "31340", "31343", "31344", "31345", "31346", "31347", "31348", "31349", "31350", "31355", "31359", "31363", "31367", "31368", "31369", "31370", "31372", "31373", "31374", "31376", "31378", "31381", "31382", "31385", "31386", "31388", "31389", "31391", "31392", "31394", "31398", "31399", "31400", "31401", "31403", "31406", "31407", "31409", "31410", "31411", "31413", "31415", "31418", "31422", "31424", "31425", "31426", "31427", "31428", "31429", "31432", "31434", "31436", "31438", "31441", "31443", "31444", "31445", "31446", "31450", "31452", "31453", "31454", "31457", "31458", "31459", "31461", "31463", "31465", "31466", "31468", "31469", "31472", "31474", "31478", "31480", "31482", "31484", "31485", "31487", "31489", "31492", "31493", "31494", "31495", "31497", "31500", "31501", "31505", "31508", "31513", "31515", "31517", "31519", "31521", "31523", "31528", "31531", "31533", "31537", "31538", "31539", "31546", "31548", "31550", "31553", "31555", "31557", "31558", "31561", "31562", "31564", "31566", "31567", "31568", "31580", "31581", "31582", "31585", "31586", "31588", "31589", "31590", "31595", "31596", "31597", "31604", "31606", "31607", "31611", "31612", "31614", "31616", "31619", "31621", "31622", "31626", "31627", "31628", "31629", "31631", "31633", "31637", "31639", "31643", "31646", "31647", "31652", "31654", "31655", "31660", "31661", "31662", "31663", "31665", "31666", "31669", "31671", "31673", "31674", "31675", "31676", "31678", "31681", "31682", "31689", "31690", "31691", "31692", "31698", "31701", "31703", "31705", "31706", "31709", "31713", "31714", "31715", "31716", "31719", "31720", "31721", "31723", "31725", "31726", "31727", "31728", "31730", "31732", "31733", "31734", "31738", "31739", "31740", "31743", "31744", "31745", "31747", "31751", "31753", "31756", "31759", "31760", "31761", "31762", "31766", "31768", "31769", "31770", "31771", "31772", "31773", "31781", "31785", "31787", "31789", "31790", "31792", "31793", "31795", "31797", "31798", "31800", "31808", "31810", "31815", "31819", "31820", "31827", "31830", "31834", "31835", "31836", "31837", "31841", "31844", "31845", "31847", "31848", "31850", "31851", "31852", "31853", "31854", "31856", "31857", "31858", "31859", "31866", "31869", "31872", "31875", "31876", "31877", "31878", "31879", "31880", "31881", "31882", "31889", "31891", "31893", "31896", "31897", "31898", "31901", "31902", "31903", "31904", "31907", "31909", "31911", "31913", "31915", "31919", "31923", "31924", "31925", "31926", "31927", "31928", "31932", "31934", "31938", "31940", "31941", "31942", "31943", "31952", "31953", "31957", "31959", "31961", "31968", "31970", "31972", "31974", "31976", "31977", "31980", "31983", "31984", "31986", "31989", "31994", "31995", "31998", "32005", "32010", "32011", "32016", "32018", "32019", "32023", "32026", "32027", "32028", "32029", "32030", "32033", "32034", "32036", "32038", "32039", "32042", "32045", "32048", "32050", "32053", "32061", "32062", "32063", "32065", "32067", "32068", "32071", "32073", "32074", "32075", "32076", "32077", "32080", "32081", "32082", "32084", "32088", "32090", "32091", "32092", "32095", "32096", "32098", "32099", "32100", "32102", "32103", "32104", "32105", "32106", "32107", "32109", "32110", "32112", "32114", "32120", "32122", "32123", "32124", "32126", "32127", "32128", "32132", "32133", "32134", "32137", "32142", "32147", "32149", "32150", "32153", "32154", "32159", "32162", "32163", "32165", "32168", "32169", "32170", "32171", "32174", "32176", "32179", "32180", "32181", "32185", "32188", "32195", "32197", "32199", "32200", "32201", "32202", "32203", "32204", "32205", "32208", "32209", "32211", "32212", "32213", "32214", "32218", "32219", "32220", "32221", "32223", "32224", "32228", "32233", "32235", "32236", "32238", "32239", "32240", "32243", "32244", "32245", "32246", "32247", "32248", "32249", "32250", "32256", "32258", "32260", "32263", "32266", "32267", "32270", "32272", "32274", "32276", "32278", "32284", "32285", "32287", "32289", "32292", "32295", "32297", "32298", "32301", "32302", "32303", "32304", "32305", "32307", "32310", "32312", "32313", "32314", "32315", "32316", "32317", "32318", "32321", "32326", "32328", "32329", "32330", "32332", "32333", "32334", "32338", "32339", "32340", "32344", "32345", "32351", "32353", "32355", "32356", "32358", "32359", "32360", "32361", "32363", "32364", "32365", "32368", "32372", "32374", "32375", "32376", "32377", "32379", "32384", "32385", "32387", "32388", "32389", "32390", "32393", "32394", "32398", "32402", "32403", "32405", "32406", "32410", "32411", "32412", "32414", "32415", "32418", "32420", "32421", "32422", "32423", "32424", "32428", "32429", "32431", "32432", "32433", "32434", "32435", "32437", "32439", "32440", "32441", "32448", "32449", "32450", "32451", "32455", "32456", "32459", "32463", "32465", "32466", "32467", "32469", "32471", "32472", "32474", "32475", "32476", "32479", "32480", "32481", "32482", "32483", "32484", "32485", "32488", "32490", "32492", "32495", "32496", "32497", "32499", "32501", "32502", "32505", "32508", "32509", "32511", "32514", "32515", "32517", "32519", "32520", "32521", "32522", "32527", "32532", "32534", "32535", "32540", "32542", "32543", "32544", "32545", "32546", "32548", "32549", "32550", "32551", "32552", "32554", "32555", "32562", "32565", "32569", "32570", "32572", "32575", "32576", "32577", "32578", "32584", "32586", "32591", "32592", "32593", "32594", "32596", "32599", "32600", "32601", "32604", "32609", "32612", "32613", "32615", "32616", "32620", "32621", "32623", "32626", "32628", "32630", "32631", "32632", "32635", "32636", "32637", "32639", "32640", "32641", "32642", "32643", "32647", "32648", "32649", "32650", "32653", "32654", "32656", "32657", "32658", "32660", "32661", "32662", "32666", "32667", "32668", "32676", "32677", "32679", "32682", "32687", "32688", "32690", "32692", "32693", "32694", "32695", "32697", "32701", "32704", "32705", "32706", "32709", "32712", "32715", "32717", "32721", "32722", "32725", "32726", "32727", "32728", "32729", "32731", "32733", "32734", "32738", "32740", "32741", "32743", "32745", "32746", "32747", "32749", "32750", "32759", "32760", "32762", "32764", "32765", "32766", "32767", "32773", "32775", "32779", "32780", "32781", "32782", "32783", "32784", "32787", "32788", "32792", "32793", "32794", "32797", "32799", "32802", "32803", "32804", "32805", "32806", "32807", "32808", "32813", "32814", "32815", "32818", "32819", "32820", "32821", "32827", "32828", "32829", "32831", "32832", "32833", "32834", "32839", "32841", "32842", "32844", "32850", "32852", "32854", "32855", "32857", "32859", "32860", "32861", "32862", "32863", "32865", "32866", "32870", "32871", "32873", "32874", "32876", "32878", "32881", "32882", "32885", "32886", "32893", "32894", "32895", "32900", "32901", "32902", "32904", "32906", "32909", "32911", "32912", "32916", "32917", "32918", "32921", "32924", "32925", "32926", "32928", "32929", "32932", "32933", "32936", "32937", "32938", "32940", "32945", "32947", "32948", "32949", "32950", "32951", "32955", "32956", "32958", "32960", "32961", "32963", "32965", "32966", "32967", "32969", "32970", "32973", "32975", "32976", "32977", "32979", "32980", "32982", "32983", "32986", "32988", "32989", "32990", "32992", "32994", "32996", "32998", "33000", "33004", "33005", "33007", "33009", "33011", "33013", "33014", "33015", "33019", "33020", "33021", "33022", "33025", "33027", "33028", "33030", "33031", "33033", "33034", "33036", "33037", "33039", "33041", "33042", "33043", "33045", "33046", "33047", "33049", "33050", "33051", "33052", "33054", "33055", "33056", "33057", "33058", "33060", "33061", "33064", "33066", "33067", "33068", "33069", "33077", "33078", "33079", "33081", "33082", "33083", "33086", "33087", "33092", "33094", "33096", "33097", "33098", "33100", "33102", "33103", "33105", "33106", "33107", "33110", "33111", "33116", "33118", "33119", "33120", "33121", "33122", "33123", "33125", "33128", "33129", "33130", "33133", "33134", "33135", "33138", "33139", "33141", "33142", "33146", "33147", "33148", "33153", "33154", "33160", "33166", "33167", "33168", "33169", "33170", "33171", "33173", "33174", "33175", "33177", "33178", "33179", "33181", "33186", "33187", "33189", "33192", "33193", "33199", "33200", "33201", "33203", "33206", "33207", "33209", "33210", "33212", "33214", "33215", "33216", "33217", "33221", "33224", "33225", "33227", "33230", "33236", "33237", "33238", "33240", "33242", "33244", "33245", "33247", "33248", "33251", "33252", "33259", "33261", "33262", "33263", "33265", "33267", "33268", "33270", "33271", "33272", "33273", "33275", "33277", "33280", "33281", "33282", "33285", "33286", "33287", "33288", "33290", "33291", "33294", "33295", "33296", "33297", "33298", "33300", "33301", "33303", "33304", "33307", "33311", "33314", "33315", "33317", "33318", "33319", "33320", "33321", "33323", "33324", "33326", "33327", "33328", "33329", "33331", "33332", "33333", "33336", "33338", "33340", "33344", "33345", "33346", "33348", "33351", "33355", "33358", "33361", "33364", "33366", "33367", "33371", "33373", "33375", "33376", "33377", "33378", "33382", "33383", "33385", "33388", "33390", "33391", "33393", "33402", "33403", "33404", "33405", "33407", "33409", "33410", "33414", "33416", "33418", "33420", "33421", "33423", "33424", "33425", "33428", "33430", "33431", "33432", "33436", "33438", "33439", "33440", "33441", "33443", "33445", "33447", "33449", "33452", "33454", "33465", "33467", "33469", "33473", "33479", "33481", "33483", "33484", "33485", "33487", "33491", "33494", "33497", "33498", "33499", "33500", "33501", "33504", "33505", "33509", "33511", "33515", "33517", "33518", "33519", "33522", "33523", "33524", "33527", "33528", "33529", "33530", "33531", "33532", "33533", "33534", "33539", "33542", "33543", "33544", "33546", "33547", "33550", "33552", "33553", "33554", "33556", "33558", "33559", "33561", "33564", "33565", "33567", "33568", "33571", "33572", "33573", "33578", "33584", "33586", "33588", "33589", "33593", "33594", "33597", "33599", "33600", "33601", "33602", "33605", "33606", "33607", "33609", "33612", "33613", "33617", "33619", "33620", "33621", "33622", "33624", "33626", "33628", "33630", "33631", "33633", "33641", "33642", "33644", "33648", "33649", "33651", "33653", "33654", "33656", "33657", "33659", "33661", "33662", "33665", "33668", "33670", "33671", "33673", "33675", "33676", "33677", "33678", "33679", "33680", "33682", "33683", "33684", "33687", "33689", "33690", "33692", "33693", "33694", "33695", "33696", "33699", "33701", "33702", "33703", "33704", "33706", "33707", "33710", "33711", "33712", "33713", "33718", "33720", "33721", "33722", "33723", "33725", "33726", "33727", "33729", "33731", "33733", "33735", "33740", "33741", "33742", "33751", "33752", "33755", "33759", "33760", "33761", "33765", "33766", "33768", "33770", "33773", "33776", "33779", "33780", "33785", "33793", "33797", "33798", "33799", "33800", "33801", "33805", "33807", "33814", "33818", "33823", "33826", "33829", "33830", "33831", "33833", "33834", "33836", "33837", "33840", "33843", "33846", "33849", "33850", "33851", "33854", "33855", "33859", "33862", "33863", "33866", "33867", "33869", "33870", "33871", "33872", "33873", "33875", "33877", "33883", "33884", "33888", "33890", "33891", "33893", "33894", "33898", "33899", "33905", "33906", "33907", "33908", "33909", "33910", "33913", "33914", "33917", "33923", "33924", "33930", "33931", "33933", "33936", "33938", "33941", "33945", "33946", "33951", "33954", "33956", "33958", "33959", "33961", "33963", "33965", "33966", "33968", "33970", "33971", "33973", "33974", "33978", "33984", "33987", "33988", "33990", "33992", "33993", "33994", "33995", "33997", "33999", "34000", "34002", "34003", "34004", "34010", "34011", "34012", "34013", "34014", "34017", "34019", "34022", "34023", "34024", "34025", "34026", "34029", "34030", "34034", "34039", "34041", "34043", "34044", "34046", "34047", "34049", "34055", "34056", "34057", "34059", "34065", "34072", "34081", "34084", "34085", "34086", "34088", "34089", "34094", "34096", "34097", "34098", "34099", "34102", "34104", "34106", "34107", "34108", "34109", "34110", "34111", "34113", "34118", "34119", "34120", "34121", "34122", "34125", "34126", "34128", "34129", "34133", "34134", "34136", "34140", "34141", "34142", "34143", "34144", "34145", "34151", "34152", "34154", "34155", "34157", "34159", "34161", "34162", "34165", "34166", "34167", "34168", "34171", "34172", "34173", "34175", "34177", "34178", "34179", "34185", "34190", "34191", "34192", "34194", "34195", "34196", "34197", "34205", "34206", "34208", "34209", "34210", "34211", "34212", "34213", "34214", "34215", "34217", "34218", "34219", "34221", "34224", "34225", "34227", "34228", "34232", "34233", "34234", "34235", "34237", "34238", "34239", "34240", "34241", "34242", "34243", "34247", "34248", "34249", "34250", "34255", "34258", "34260", "34264", "34267", "34268", "34272", "34276", "34280", "34283", "34285", "34287", "34290", "34291", "34292", "34293", "34294", "34297", "34299", "34300", "34301", "34302", "34304", "34307", "34308", "34309", "34311", "34312", "34313", "34315", "34317", "34318", "34319", "34322", "34323", "34325", "34326", "34327", "34329", "34330", "34331", "34337", "34341", "34342", "34345", "34346", "34348", "34349", "34350", "34355", "34356", "34357", "34362", "34366", "34367", "34368", "34369", "34370", "34374", "34375", "34377", "34378", "34379", "34380", "34381", "34382", "34386", "34389", "34390", "34392", "34395", "34397", "34400", "34402", "34406", "34408", "34409", "34410", "34411", "34413", "34414", "34415", "34416", "34418", "34420", "34421", "34423", "34424", "34426", "34429", "34431", "34434", "34435", "34437", "34439", "34440", "34443", "34445", "34446", "34449", "34450", "34451", "34452", "34453", "34455", "34456", "34458", "34459", "34460", "34463", "34468", "34470", "34471", "34474", "34478", "34479", "34480", "34481", "34482", "34483", "34484", "34486", "34487", "34490", "34493", "34494", "34495", "34496", "34498", "34499", "34503", "34504", "34506", "34507", "34509", "34510", "34515", "34517", "34518", "34520", "34522", "34523", "34525", "34527", "34532", "34533", "34535", "34537", "34542", "34543", "34546", "34547", "34550", "34553", "34554", "34556", "34557", "34558", "34559", "34561", "34565", "34568", "34569", "34571", "34573", "34574", "34575", "34576", "34578", "34580", "34581", "34584", "34588", "34590", "34591", "34592", "34593", "34594", "34595", "34597", "34601", "34603", "34604", "34605", "34606", "34607", "34608", "34610", "34611", "34613", "34615", "34616", "34617", "34618", "34620", "34621", "34622", "34626", "34627", "34629", "34630", "34631", "34634", "34635", "34640", "34643", "34644", "34645", "34648", "34649", "34651", "34652", "34653", "34654", "34666", "34668", "34670", "34671", "34672", "34676", "34677", "34681", "34682", "34683", "34685", "34686", "34688", "34689", "34690", "34691", "34692", "34693", "34694", "34695", "34699", "34700", "34701", "34703", "34705", "34707", "34708", "34710", "34712", "34713", "34715", "34716", "34718", "34720", "34721", "34724", "34727", "34728", "34732", "34734", "34735", "34737", "34738", "34739", "34746", "34747", "34748", "34750", "34755", "34757", "34758", "34759", "34761", "34762", "34769", "34771", "34772", "34775", "34777", "34778", "34779", "34780", "34783", "34785", "34786", "34788", "34790", "34791", "34793", "34795", "34796", "34798", "34799", "34803", "34805", "34808", "34809", "34810", "34814", "34817", "34820", "34825", "34827", "34830", "34832", "34833", "34836", "34837", "34838", "34839", "34840", "34842", "34845", "34846", "34849", "34854", "34857", "34860", "34861", "34864", "34865", "34866", "34871", "34872", "34875", "34879", "34880", "34881", "34883", "34885", "34886", "34888", "34892", "34894", "34895", "34896", "34897", "34899", "34905", "34906", "34907", "34911", "34912", "34913", "34914", "34917", "34918", "34921", "34922", "34923", "34925", "34926", "34928", "34929", "34931", "34932", "34934", "34935", "34936", "34943", "34946", "34947", "34948", "34950", "34952", "34954", "34955", "34958", "34961", "34962", "34966", "34967", "34968", "34969", "34971", "34976", "34977", "34979", "34981", "34982", "34983", "34984", "34985", "34986", "34988", "34989", "34992", "34994", "34995", "34996", "34997", "34998", "35001", "35002", "35007", "35010", "35011", "35013", "35015", "35016", "35018", "35022", "35024", "35025", "35026", "35028", "35034", "35036", "35040", "35041", "35042", "35047", "35052", "35055", "35056", "35058", "35059", "35060", "35062", "35065", "35068", "35073", "35074", "35075", "35077", "35078", "35080", "35082", "35083", "35087", "35088", "35096", "35097", "35100", "35101", "35102", "35104", "35106", "35107", "35110", "35111", "35112", "35114", "35115", "35116", "35117", "35118", "35119", "35120", "35121", "35126", "35127", "35128", "35133", "35134", "35137", "35138", "35141", "35142", "35145", "35147", "35149", "35150", "35151", "35153", "35155", "35157", "35158", "35160", "35165", "35174", "35175", "35176", "35177", "35180", "35182", "35183", "35184", "35185", "35187", "35189", "35191", "35192", "35193", "35194", "35197", "35202", "35203", "35206", "35207", "35208", "35209", "35210", "35211", "35213", "35214", "35215", "35216", "35217", "35218", "35221", "35222", "35223", "35226", "35227", "35228", "35232", "35236", "35238", "35239", "35240", "35241", "35243", "35245", "35248", "35249", "35253", "35255", "35257", "35259", "35260", "35261", "35262", "35265", "35267", "35268", "35269", "35270", "35271", "35273", "35274", "35278", "35280", "35281", "35284", "35285", "35289", "35290", "35291", "35292", "35293", "35294", "35297", "35301", "35302", "35303", "35305", "35306", "35308", "35310", "35312", "35315", "35317", "35326", "35327", "35331", "35332", "35333", "35335", "35336", "35337", "35340", "35342", "35345", "35346", "35347", "35351", "35352", "35353", "35354", "35355", "35356", "35357", "35359", "35360", "35363", "35365", "35366", "35367", "35368", "35370", "35372", "35376", "35377", "35378", "35381", "35383", "35385", "35389", "35390", "35393", "35396", "35397", "35400", "35401", "35404", "35406", "35407", "35408", "35410", "35411", "35412", "35413", "35415", "35417", "35423", "35424", "35425", "35426", "35428", "35429", "35430", "35435", "35437", "35438", "35441", "35448", "35449", "35450", "35452", "35453", "35454", "35456", "35460", "35461", "35462", "35464", "35466", "35467", "35470", "35471", "35474", "35475", "35476", "35477", "35478", "35479", "35483", "35485", "35486", "35487", "35489", "35492", "35493", "35497", "35498", "35499", "35500", "35501", "35504", "35506", "35509", "35511", "35512", "35514", "35518", "35525", "35527", "35532", "35533", "35535", "35536", "35538", "35539", "35540", "35541", "35545", "35546", "35547", "35551", "35552", "35553", "35554", "35559", "35563", "35564", "35565", "35567", "35568", "35569", "35570", "35575", "35576", "35577", "35579", "35580", "35582", "35584", "35585", "35587", "35589", "35590", "35591", "35592", "35593", "35596", "35601", "35602", "35603", "35604", "35606", "35608", "35610", "35612", "35615", "35616", "35618", "35619", "35622", "35623", "35624", "35625", "35627", "35629", "35631", "35633", "35634", "35639", "35640", "35641", "35642", "35643", "35644", "35645", "35647", "35650", "35651", "35652", "35653", "35658", "35660", "35661", "35662", "35665", "35666", "35667", "35670", "35674", "35675", "35676", "35679", "35680", "35686", "35690", "35693", "35694", "35695", "35701", "35704", "35705", "35707", "35708", "35709", "35710", "35711", "35713", "35715", "35717", "35719", "35721", "35722", "35723", "35730", "35731", "35732", "35733", "35734", "35735", "35737", "35738", "35739", "35740", "35741", "35742", "35744", "35745", "35748", "35749", "35750", "35752", "35755", "35756", "35758", "35759", "35760", "35761", "35769", "35770", "35771", "35773", "35774", "35776", "35777", "35780", "35783", "35784", "35786", "35787", "35788", "35789", "35790", "35791", "35793", "35795", "35796", "35797", "35800", "35801", "35806", "35808", "35809", "35810", "35811", "35812", "35813", "35819", "35820", "35821", "35822", "35823", "35824", "35827", "35828", "35830", "35831", "35833", "35834", "35837", "35840", "35844", "35845", "35857", "35858", "35860", "35862", "35867", "35869", "35871", "35873", "35874", "35875", "35877", "35878", "35886", "35888", "35890", "35894", "35896", "35897", "35899", "35901", "35903", "35904", "35905", "35906", "35907", "35909", "35913", "35914", "35915", "35919", "35920", "35922", "35923", "35924", "35925", "35926", "35928", "35931", "35932", "35933", "35934", "35936", "35937", "35938", "35939", "35942", "35945", "35946", "35947", "35949", "35950", "35951", "35955", "35956", "35957", "35958", "35960", "35961", "35962", "35963", "35964", "35965", "35966", "35967", "35968", "35972", "35973", "35974", "35980", "35981", "35987", "35991", "35993", "35994", "35995", "35996", "35997", "35998", "36000", "36006", "36010", "36011", "36014", "36015", "36018", "36020", "36022", "36025", "36026", "36027", "36028", "36029", "36030", "36032", "36034", "36035", "36036", "36037", "36038", "36039", "36040", "36043", "36044", "36045", "36046", "36049", "36052", "36053", "36054", "36055", "36056", "36058", "36061", "36062", "36066", "36067", "36069", "36073", "36076", "36080", "36082", "36083", "36084", "36086", "36087", "36089", "36091", "36092", "36093", "36095", "36097", "36099", "36100", "36101", "36103", "36104", "36105", "36109", "36110", "36113", "36114", "36117", "36118", "36120", "36121", "36122", "36123", "36124", "36125", "36131", "36132", "36133", "36135", "36136", "36137", "36138", "36139", "36140", "36141", "36143", "36144", "36146", "36149", "36152", "36154", "36155", "36160", "36163", "36164", "36165", "36166", "36167", "36168", "36169", "36171", "36173", "36175", "36177", "36178", "36179", "36181", "36184", "36185", "36187", "36188", "36190", "36191", "36195", "36196", "36197", "36198", "36199", "36200", "36201", "36204", "36206", "36207", "36208", "36211", "36212", "36213", "36215", "36216", "36218", "36219", "36220", "36221", "36225", "36227", "36229", "36230", "36237", "36238", "36243", "36244", "36247", "36249", "36254", "36255", "36259", "36260", "36261", "36264", "36268", "36269", "36271", "36277", "36278", "36281", "36283", "36286", "36293", "36294", "36299", "36301", "36302", "36303", "36304", "36306", "36310", "36312", "36313", "36315", "36316", "36317", "36318", "36320", "36323", "36324", "36325", "36326", "36332", "36333", "36334", "36339", "36340", "36341", "36342", "36344", "36345", "36346", "36347", "36350", "36351", "36352", "36353", "36356", "36357", "36358", "36362", "36363", "36364", "36366", "36367", "36374", "36375", "36376", "36378", "36379", "36380", "36381", "36390", "36391", "36392", "36395", "36396", "36397", "36398", "36399", "36400", "36401", "36402", "36405", "36406", "36408", "36409", "36410", "36412", "36416", "36417", "36419", "36420", "36421", "36424", "36426", "36427", "36430", "36432", "36434", "36436", "36439", "36441", "36445", "36450", "36451", "36452", "36455", "36462", "36464", "36465", "36467", "36468", "36469", "36470", "36471", "36472", "36473", "36474", "36475", "36478", "36481", "36482", "36486", "36488", "36489", "36491", "36492", "36493", "36494", "36495", "36496", "36498", "36503", "36504", "36505", "36507", "36510", "36516", "36519", "36521", "36523", "36524", "36527", "36529", "36531", "36532", "36533", "36534", "36535", "36537", "36540", "36541", "36546", "36547", "36548", "36550", "36552", "36555", "36560", "36561", "36562", "36563", "36564", "36565", "36566", "36567", "36568", "36573", "36578", "36582", "36583", "36584", "36585", "36586", "36587", "36588", "36590", "36595", "36596", "36597", "36598", "36601", "36602", "36603", "36606", "36607", "36608", "36610", "36611", "36613", "36615", "36616", "36617", "36621", "36622", "36623", "36624", "36625", "36627", "36628", "36629", "36631", "36632", "36638", "36642", "36644", "36645", "36647", "36648", "36649", "36650", "36651", "36656", "36657", "36658", "36659", "36660", "36669", "36670", "36672", "36675", "36676", "36677", "36678", "36680", "36684", "36685", "36687", "36688", "36689", "36690", "36691", "36695", "36700", "36702", "36703", "36706", "36707", "36708", "36710", "36712", "36714", "36715", "36718", "36719", "36720", "36721", "36723", "36724", "36726", "36733", "36737", "36739", "36741", "36743", "36745", "36747", "36748", "36752", "36757", "36760", "36761", "36763", "36764", "36767", "36768", "36775", "36776", "36778", "36779", "36781", "36786", "36789", "36794", "36795", "36799", "36800", "36802", "36804", "36809", "36810", "36812", "36814", "36821", "36823", "36826", "36828", "36831", "36832", "36833", "36840", "36841", "36843", "36844", "36846", "36847", "36848", "36849", "36851", "36854", "36855", "36856", "36857", "36858", "36859", "36860", "36861", "36864", "36865", "36866", "36867", "36871", "36872", "36873", "36874", "36875", "36876", "36878", "36881", "36882", "36883", "36884", "36885", "36889", "36890", "36893", "36894", "36898", "36899", "36900", "36903", "36906", "36907", "36908", "36909", "36910", "36916", "36923", "36931", "36932", "36934", "36935", "36936", "36941", "36946", "36947", "36948", "36950", "36951", "36952", "36955", "36956", "36958", "36959", "36962", "36964", "36965", "36966", "36967", "36968", "36971", "36973", "36974", "36975", "36976", "36978", "36979", "36981", "36982", "36985", "36986", "36987", "36988", "36991", "36994", "36997", "37000", "37005", "37007", "37010", "37016", "37019", "37020", "37021", "37023", "37028", "37032", "37033", "37035", "37039", "37040", "37042", "37048", "37051", "37052", "37055", "37056", "37057", "37058", "37060", "37064", "37066", "37067", "37073", "37075", "37076", "37079", "37080", "37082", "37083", "37085", "37087", "37088", "37089", "37091", "37092", "37093", "37094", "37095", "37096", "37097", "37102", "37103", "37104", "37105", "37107", "37109", "37110", "37111", "37113", "37115", "37116", "37118", "37120", "37122", "37123", "37124", "37127", "37128", "37129", "37130", "37132", "37134", "37136", "37138", "37139", "37141", "37142", "37147", "37148", "37153", "37155", "37156", "37162", "37163", "37165", "37166", "37167", "37168", "37173", "37174", "37176", "37179", "37180", "37181", "37182", "37183", "37186", "37187", "37189", "37195", "37199", "37201", "37203", "37204", "37206", "37209", "37214", "37217", "37220", "37224", "37225", "37230", "37231", "37232", "37234", "37235", "37236", "37241", "37242", "37243", "37244", "37246", "37248", "37249", "37251", "37253", "37254", "37255", "37257", "37258", "37259", "37260", "37266", "37267", "37271", "37277", "37278", "37279", "37280", "37282", "37283", "37286", "37287", "37289", "37292", "37293", "37297", "37298", "37299", "37301", "37305", "37306", "37307", "37308", "37310", "37312", "37313", "37314", "37317", "37320", "37321", "37325", "37327", "37328", "37329", "37332", "37335", "37337", "37338", "37340", "37341", "37347", "37350", "37351", "37352", "37353", "37354", "37356", "37358", "37359", "37361", "37364", "37366", "37367", "37375", "37376", "37377", "37378", "37379", "37380", "37383", "37385", "37386", "37388", "37389", "37390", "37391", "37396", "37398", "37400", "37401", "37402", "37403", "37404", "37405", "37408", "37409", "37411", "37412", "37413", "37414", "37416", "37417", "37419", "37420", "37423", "37425", "37428", "37431", "37433", "37437", "37438", "37439", "37441", "37443", "37445", "37448", "37451", "37452", "37454", "37455", "37462", "37463", "37464", "37465", "37466", "37467", "37469", "37470", "37471", "37473", "37474", "37476", "37477", "37479", "37481", "37483", "37484", "37486", "37490", "37493", "37494", "37497", "37499", "37500", "37501", "37502", "37503", "37504", "37506", "37510", "37511", "37513", "37518", "37523", "37524", "37527", "37529", "37535", "37536", "37540", "37542", "37543", "37546", "37547", "37548", "37549", "37551", "37556", "37558", "37561", "37565", "37566", "37567", "37568", "37572", "37573", "37579", "37582", "37584", "37585", "37586", "37587", "37593", "37595", "37596", "37597", "37598", "37601", "37603", "37604", "37606", "37610", "37611", "37613", "37614", "37615", "37620", "37621", "37623", "37624", "37625", "37626", "37627", "37628", "37632", "37635", "37636", "37638", "37639", "37641", "37646", "37647", "37648", "37651", "37652", "37654", "37655", "37656", "37658", "37660", "37664", "37665", "37666", "37668", "37671", "37672", "37673", "37674", "37676", "37679", "37680", "37681", "37683", "37696", "37698", "37699", "37703", "37705", "37707", "37709", "37711", "37713", "37714", "37716", "37717", "37720", "37722", "37724", "37727", "37728", "37729", "37730", "37731", "37734", "37735", "37737", "37738", "37739", "37740", "37742", "37743", "37747", "37749", "37750", "37752", "37753", "37755", "37756", "37758", "37759", "37760", "37761", "37764", "37765", "37766", "37768", "37770", "37771", "37776", "37785", "37787", "37788", "37791", "37792", "37795", "37797", "37798", "37801", "37802", "37806", "37808", "37810", "37811", "37813", "37815", "37817", "37818", "37824", "37826", "37827", "37831", "37832", "37834", "37837", "37838", "37840", "37841", "37842", "37845", "37847", "37852", "37856", "37857", "37859", "37861", "37865", "37866", "37868", "37869", "37871", "37873", "37874", "37875", "37879", "37883", "37886", "37887", "37890", "37894", "37895", "37896", "37898", "37899", "37903", "37904", "37905", "37906", "37907", "37909", "37915", "37916", "37917", "37918", "37919", "37920", "37923", "37925", "37927", "37930", "37932", "37935", "37936", "37937", "37940", "37941", "37942", "37947", "37950", "37952", "37953", "37955", "37956", "37957", "37959", "37961", "37963", "37964", "37965", "37967", "37968", "37971", "37973", "37974", "37975", "37976", "37979", "37980", "37982", "37985", "37986", "37987", "37989", "37990", "37992", "37994", "37995", "38000", "38001", "38004", "38005", "38014", "38015", "38017", "38018", "38021", "38023", "38024", "38026", "38027", "38031", "38032", "38034", "38035", "38038", "38039", "38040", "38041", "38042", "38045", "38046", "38049", "38050", "38051", "38052", "38053", "38059", "38060", "38061", "38071", "38072", "38073", "38074", "38075", "38076", "38077", "38080", "38081", "38084", "38088", "38096", "38098", "38099", "38100", "38101", "38102", "38104", "38105", "38106", "38109", "38110", "38113", "38114", "38116", "38117", "38118", "38122", "38124", "38125", "38128", "38129", "38130", "38133", "38135", "38137", "38138", "38141", "38143", "38145", "38150", "38151", "38152", "38156", "38157", "38159", "38162", "38164", "38167", "38168", "38170", "38171", "38172", "38174", "38175", "38177", "38178", "38179", "38180", "38181", "38182", "38183", "38184", "38185", "38186", "38188", "38189", "38195", "38198", "38200", "38201", "38202", "38204", "38208", "38209", "38211", "38213", "38215", "38217", "38219", "38221", "38223", "38224", "38228", "38229", "38232", "38234", "38235", "38238", "38242", "38247", "38248", "38249", "38251", "38256", "38258", "38259", "38262", "38264", "38266", "38271", "38272", "38273", "38275", "38279", "38284", "38286", "38290", "38291", "38293", "38294", "38296", "38297", "38298", "38299", "38302", "38303", "38305", "38306", "38307", "38311", "38313", "38319", "38321", "38322", "38324", "38325", "38332", "38333", "38339", "38340", "38341", "38342", "38346", "38347", "38348", "38350", "38352", "38353", "38355", "38356", "38357", "38358", "38359", "38360", "38362", "38364", "38366", "38368", "38371", "38372", "38373", "38377", "38378", "38379", "38383", "38384", "38385", "38390", "38391", "38392", "38395", "38396", "38399", "38402", "38403", "38404", "38406", "38407", "38414", "38415", "38416", "38417", "38418", "38420", "38421", "38424", "38426", "38430", "38433", "38436", "38439", "38440", "38442", "38445", "38448", "38451", "38454", "38459", "38460", "38461", "38462", "38465", "38467", "38471", "38473", "38474", "38476", "38477", "38480", "38481", "38484", "38486", "38489", "38491", "38495", "38499", "38502", "38503", "38504", "38507", "38508", "38512", "38513", "38514", "38515", "38516", "38518", "38519", "38520", "38522", "38525", "38528", "38532", "38533", "38534", "38535", "38536", "38537", "38538", "38543", "38547", "38550", "38551", "38553", "38554", "38555", "38556", "38557", "38558", "38559", "38563", "38565", "38567", "38568", "38569", "38571", "38572", "38573", "38577", "38579", "38586", "38588", "38593", "38594", "38595", "38598", "38599", "38604", "38605", "38606", "38607", "38609", "38611", "38612", "38613", "38615", "38617", "38619", "38620", "38623", "38624", "38626", "38627", "38630", "38633", "38634", "38636", "38637", "38641", "38642", "38643", "38644", "38646", "38651", "38656", "38658", "38660", "38661", "38662", "38663", "38664", "38665", "38666", "38667", "38675", "38676", "38678", "38679", "38681", "38685", "38686", "38689", "38692", "38696", "38697", "38700", "38703", "38704", "38705", "38711", "38713", "38716", "38717", "38720", "38724", "38727", "38728", "38731", "38732", "38734", "38738", "38739", "38741", "38742", "38743", "38744", "38745", "38749", "38751", "38752", "38756", "38758", "38761", "38762", "38764", "38765", "38766", "38768", "38770", "38778", "38779", "38781", "38787", "38790", "38792", "38797", "38798", "38799", "38800", "38801", "38802", "38808", "38810", "38811", "38812", "38815", "38817", "38820", "38821", "38822", "38824", "38826", "38827", "38829", "38831", "38833", "38836", "38837", "38838", "38841", "38843", "38845", "38846", "38849", "38852", "38853", "38854", "38856", "38858", "38860", "38861", "38862", "38865", "38870", "38871", "38872", "38875", "38876", "38878", "38879", "38880", "38883", "38885", "38887", "38888", "38889", "38891", "38894", "38895", "38897", "38898", "38901", "38903", "38904", "38905", "38906", "38907", "38909", "38910", "38912", "38917", "38921", "38926", "38929", "38930", "38932", "38935", "38937", "38941", "38942", "38945", "38946", "38947", "38955", "38958", "38960", "38967", "38968", "38969", "38970", "38972", "38975", "38976", "38977", "38978", "38979", "38980", "38981", "38983", "38984", "38986", "38988", "38989", "38990", "38991", "38993", "38994", "38995", "38996", "38997", "39002", "39004", "39005", "39006", "39007", "39009", "39011", "39012", "39013", "39019", "39020", "39022", "39023", "39028", "39033", "39035", "39040", "39041", "39044", "39047", "39048", "39051", "39053", "39054", "39055", "39057", "39058", "39059", "39063", "39064", "39067", "39068", "39070", "39071", "39075", "39076", "39078", "39080", "39084", "39085", "39086", "39087", "39089", "39090", "39092", "39094", "39096", "39098", "39099", "39100", "39101", "39102", "39104", "39105", "39106", "39108", "39109", "39111", "39112", "39118", "39120", "39121", "39122", "39123", "39124", "39125", "39126", "39127", "39128", "39132", "39134", "39136", "39140", "39141", "39142", "39144", "39148", "39150", "39151", "39152", "39153", "39156", "39158", "39159", "39161", "39162", "39163", "39164", "39166", "39167", "39170", "39171", "39172", "39173", "39178", "39180", "39181", "39182", "39184", "39188", "39192", "39195", "39197", "39199", "39202", "39203", "39205", "39208", "39211", "39213", "39216", "39219", "39220", "39221", "39228", "39230", "39231", "39233", "39235", "39236", "39237", "39241", "39243", "39244", "39248", "39249", "39252", "39254", "39255", "39256", "39257", "39258", "39259", "39263", "39265", "39266", "39267", "39268", "39271", "39272", "39274", "39275", "39276", "39277", "39278", "39279", "39280", "39281", "39283", "39284", "39286", "39290", "39291", "39292", "39295", "39296", "39299", "39300", "39303", "39305", "39309", "39311", "39315", "39316", "39318", "39319", "39322", "39324", "39325", "39326", "39327", "39328", "39330", "39332", "39334", "39336", "39337", "39338", "39340", "39343", "39345", "39346", "39348", "39349", "39351", "39354", "39355", "39356", "39358", "39359", "39361", "39362", "39363", "39365", "39366", "39367", "39368", "39372", "39373", "39376", "39377", "39378", "39379", "39381", "39382", "39383", "39385", "39389", "39394", "39395", "39397", "39402", "39403", "39406", "39408", "39410", "39411", "39412", "39413", "39414", "39415", "39416", "39417", "39418", "39419", "39420", "39421", "39422", "39423", "39424", "39425", "39427", "39428", "39429", "39430", "39431", "39434", "39439", "39441", "39442", "39443", "39444", "39446", "39447", "39449", "39450", "39454", "39456", "39457", "39461", "39462", "39463", "39464", "39465", "39467", "39471", "39473", "39474", "39476", "39478", "39479", "39481", "39482", "39483", "39486", "39488", "39489", "39493", "39497", "39501", "39502", "39503", "39504", "39508", "39514", "39515", "39516", "39517", "39520", "39521", "39528", "39529", "39531", "39532", "39534", "39536", "39538", "39540", "39542", "39544", "39547", "39549", "39550", "39551", "39559", "39561", "39562", "39565", "39566", "39568", "39569", "39572", "39573", "39574", "39575", "39577", "39578", "39580", "39581", "39583", "39584", "39585", "39588", "39592", "39593", "39594", "39596", "39598", "39600", "39602", "39603", "39604", "39606", "39607", "39611", "39616", "39617", "39619", "39625", "39628", "39631", "39634", "39637", "39638", "39641", "39643", "39644", "39645", "39647", "39648", "39649", "39660", "39665", "39666", "39667", "39670", "39672", "39679", "39680", "39681", "39682", "39683", "39687", "39691", "39692", "39693", "39695", "39696", "39697", "39698", "39700", "39701", "39706", "39709", "39710", "39711", "39715", "39716", "39717", "39718", "39721", "39724", "39730", "39731", "39733", "39742", "39743", "39745", "39748", "39749", "39750", "39751", "39752", "39756", "39757", "39759", "39764", "39767", "39770", "39772", "39779", "39780", "39781", "39782", "39783", "39789", "39790", "39791", "39793", "39795", "39796", "39798", "39799", "39800", "39803", "39804", "39807", "39813", "39814", "39815", "39817", "39823", "39824", "39826", "39827", "39832", "39835", "39837", "39838", "39839", "39840", "39844", "39845", "39846", "39847", "39848", "39849", "39850", "39851", "39852", "39853", "39854", "39855", "39856", "39857", "39859", "39862", "39864", "39865", "39866", "39870", "39874", "39877", "39878", "39881", "39882", "39884", "39886", "39888", "39890", "39891", "39892", "39894", "39895", "39899", "39901", "39902", "39904", "39907", "39909", "39911", "39912", "39915", "39917", "39919", "39921", "39922", "39924", "39925", "39927", "39929", "39931", "39932", "39933", "39936", "39937", "39938", "39939", "39940", "39943", "39944", "39945", "39946", "39949", "39950", "39951", "39956", "39959", "39960", "39962", "39963", "39964", "39965", "39966", "39968", "39970", "39974", "39975", "39976", "39978", "39979", "39980", "39981", "39982", "39984", "39990", "39994", "39996", "39997", "40000", "40002", "40003", "40004", "40012", "40017", "40018", "40019", "40020", "40022", "40023", "40025", "40026", "40028", "40029", "40036", "40038", "40039", "40041", "40042", "40043", "40044", "40047", "40049", "40055", "40056", "40057", "40059", "40062", "40063", "40069", "40070", "40074", "40076", "40077", "40078", "40079", "40080", "40082", "40084", "40085", "40087", "40088", "40089", "40091", "40092", "40094", "40097", "40100", "40101", "40102", "40104", "40105", "40108", "40109", "40111", "40114", "40117", "40120", "40121", "40125", "40127", "40128", "40130", "40131", "40132", "40133", "40134", "40140", "40141", "40142", "40144", "40145", "40148", "40149", "40155", "40156", "40160", "40161", "40163", "40171", "40172", "40173", "40174", "40178", "40182", "40186", "40188", "40194", "40195", "40196", "40197", "40198", "40200", "40202", "40203", "40205", "40206", "40208", "40209", "40210", "40212", "40213", "40214", "40216", "40217", "40218", "40219", "40221", "40222", "40225", "40229", "40233", "40236", "40238", "40240", "40241", "40246", "40249", "40250", "40251", "40257", "40260", "40261", "40264", "40266", "40267", "40270", "40271", "40272", "40274", "40279", "40280", "40282", "40285", "40286", "40289", "40293", "40295", "40297", "40300", "40301", "40302", "40303", "40305", "40308", "40311", "40314", "40315", "40316", "40317", "40322", "40323", "40325", "40326", "40327", "40328", "40329", "40330", "40332", "40333", "40334", "40335", "40336", "40337", "40338", "40340", "40343", "40345", "40346", "40347", "40349", "40353", "40354", "40355", "40358", "40360", "40361", "40365", "40367", "40369", "40370", "40377", "40380", "40382", "40385", "40386", "40387", "40388", "40389", "40391", "40393", "40395", "40398", "40403", "40405", "40406", "40410", "40411", "40413", "40415", "40416", "40417", "40420", "40425", "40427", "40428", "40429", "40430", "40432", "40436", "40437", "40439", "40441", "40443", "40445", "40446", "40447", "40448", "40456", "40457", "40461", "40462", "40463", "40464", "40465", "40468", "40469", "40470", "40471", "40472", "40473", "40476", "40477", "40479", "40481", "40482", "40483", "40484", "40487", "40488", "40491", "40492", "40498", "40501", "40502", "40504", "40505", "40514", "40517", "40520", "40522", "40525", "40526", "40534", "40535", "40539", "40540", "40541", "40543", "40544", "40545", "40547", "40548", "40551", "40552", "40554", "40557", "40559", "40561", "40562", "40563", "40564", "40565", "40569", "40570", "40571", "40572", "40573", "40574", "40575", "40577", "40579", "40580", "40584", "40585", "40588", "40589", "40593", "40594", "40601", "40603", "40604", "40606", "40607", "40608", "40614", "40618", "40620", "40621", "40625", "40626", "40627", "40628", "40629", "40631", "40632", "40633", "40634", "40635", "40636", "40638", "40639", "40640", "40641", "40645", "40647", "40649", "40650", "40653", "40654", "40657", "40658", "40666", "40667", "40668", "40669", "40670", "40674", "40677", "40679", "40683", "40686", "40690", "40691", "40692", "40696", "40697", "40699", "40700", "40701", "40702", "40703", "40706", "40707", "40708", "40710", "40712", "40714", "40715", "40716", "40717", "40719", "40720", "40726", "40728", "40729", "40730", "40737", "40740", "40743", "40744", "40747", "40749", "40750", "40754", "40755", "40756", "40757", "40758", "40759", "40761", "40762", "40765", "40767", "40770", "40771", "40772", "40773", "40778", "40781", "40783", "40785", "40789", "40791", "40794", "40795", "40796", "40799", "40805", "40808", "40809", "40811", "40812", "40815", "40817", "40819", "40822", "40823", "40825", "40828", "40830", "40831", "40832", "40833", "40834", "40835", "40837", "40838", "40840", "40842", "40843", "40844", "40846", "40847", "40848", "40849", "40855", "40856", "40857", "40860", "40865", "40868", "40871", "40874", "40875", "40885", "40887", "40890", "40891", "40892", "40893", "40894", "40898", "40899", "40900", "40902", "40904", "40905", "40907", "40909", "40911", "40912", "40915", "40916", "40917", "40918", "40919", "40920", "40921", "40922", "40923", "40927", "40929", "40930", "40931", "40934", "40936", "40940", "40942", "40943", "40944", "40946", "40947", "40948", "40954", "40955", "40956", "40960", "40961", "40962", "40965", "40967", "40968", "40975", "40976", "40977", "40978", "40980", "40981", "40982", "40983", "40985", "40991", "40992", "40994", "41000", "41001", "41002", "41004", "41008", "41009", "41010", "41011", "41013", "41014", "41019", "41021", "41023", "41024", "41025", "41026", "41027", "41028", "41030", "41031", "41038", "41039", "41041", "41042", "41043", "41045", "41048", "41049", "41051", "41052", "41053", "41054", "41059", "41062", "41064", "41065", "41066", "41068", "41070", "41071", "41073", "41075", "41076", "41078", "41080", "41081", "41082", "41084", "41086", "41089", "41090", "41092", "41096", "41097", "41098", "41099", "41101", "41102", "41103", "41106", "41110", "41112", "41113", "41115", "41120", "41121", "41123", "41127", "41128", "41132", "41136", "41138", "41139", "41144", "41146", "41150", "41154", "41155", "41157", "41158", "41160", "41161", "41163", "41168", "41169", "41172", "41174", "41175", "41176", "41182", "41183", "41185", "41186", "41187", "41188", "41189", "41192", "41196", "41197", "41199", "41200", "41202", "41204", "41205", "41207", "41208", "41209", "41210", "41212", "41213", "41214", "41216", "41219", "41221", "41222", "41223", "41227", "41228", "41229", "41235", "41237", "41238", "41242", "41243", "41244", "41245", "41246", "41247", "41248", "41249", "41251", "41252", "41254", "41257", "41261", "41262", "41264", "41265", "41268", "41269", "41273", "41276", "41277", "41278", "41282", "41286", "41287", "41290", "41291", "41292", "41296", "41297", "41298", "41299", "41301", "41302", "41303", "41304", "41309", "41310", "41312", "41321", "41322", "41323", "41326", "41327", "41328", "41330", "41331", "41332", "41333", "41336", "41337", "41339", "41341", "41344", "41346", "41348", "41351", "41354", "41360", "41361", "41366", "41373", "41374", "41378", "41379", "41380", "41382", "41385", "41387", "41390", "41391", "41392", "41399", "41403", "41404", "41406", "41407", "41408", "41411", "41413", "41414", "41415", "41416", "41417", "41420", "41422", "41424", "41427", "41429", "41430", "41431", "41432", "41433", "41435", "41436", "41438", "41439", "41441", "41443", "41446", "41448", "41450", "41453", "41455", "41457", "41458", "41460", "41462", "41463", "41465", "41466", "41467", "41468", "41469", "41471", "41472", "41473", "41477", "41479", "41482", "41485", "41486", "41488", "41489", "41503", "41504", "41507", "41508", "41512", "41514", "41516", "41517", "41520", "41522", "41523", "41525", "41527", "41529", "41530", "41531", "41533", "41536", "41538", "41540", "41542", "41543", "41546", "41550", "41552", "41559", "41560", "41561", "41563", "41564", "41569", "41572", "41576", "41579", "41582", "41584", "41585", "41589", "41593", "41595", "41596", "41597", "41599", "41601", "41603", "41607", "41608", "41609", "41612", "41614", "41615", "41616", "41617", "41619", "41621", "41623", "41625", "41626", "41627", "41628", "41629", "41631", "41633", "41634", "41636", "41637", "41639", "41641", "41644", "41645", "41646", "41647", "41649", "41652", "41653", "41654", "41655", "41659", "41661", "41662", "41664", "41668", "41669", "41670", "41671", "41673", "41675", "41677", "41679", "41680", "41682", "41685", "41688", "41690", "41692", "41693", "41694", "41697", "41698", "41700", "41702", "41704", "41705", "41707", "41708", "41709", "41710", "41715", "41717", "41718", "41719", "41720", "41721", "41722", "41724", "41725", "41730", "41731", "41732", "41735", "41737", "41738", "41740", "41742", "41747", "41749", "41750", "41751", "41752", "41753", "41754", "41758", "41759", "41760", "41762", "41764", "41766", "41768", "41769", "41771", "41772", "41775", "41776", "41781", "41782", "41783", "41784", "41789", "41790", "41793", "41795", "41796", "41798", "41799", "41801", "41802", "41805", "41806", "41808", "41809", "41811", "41821", "41823", "41824", "41825", "41827", "41829", "41831", "41832", "41836", "41837", "41840", "41841", "41842", "41843", "41845", "41848", "41850", "41851", "41852", "41853", "41858", "41860", "41864", "41866", "41867", "41872", "41873", "41875", "41876", "41877", "41879", "41885", "41889", "41891", "41893", "41894", "41895", "41898", "41900", "41901", "41902", "41903", "41904", "41905", "41906", "41908", "41910", "41911", "41912", "41915", "41917", "41923", "41924", "41925", "41926", "41929", "41930", "41933", "41935", "41939", "41941", "41942", "41945", "41946", "41950", "41951", "41952", "41953", "41958", "41959", "41960", "41965", "41966", "41971", "41974", "41976", "41988", "41990", "41991", "41992", "41997", "42000", "42001", "42002", "42007", "42008", "42009", "42012", "42014", "42015", "42018", "42022", "42023", "42024", "42026", "42029", "42030", "42033", "42035", "42036", "42037", "42039", "42040", "42042", "42046", "42047", "42048", "42049", "42052", "42058", "42060", "42062", "42065", "42066", "42071", "42073", "42076", "42079", "42080", "42082", "42084", "42087", "42088", "42090", "42091", "42094", "42095", "42097", "42100", "42102", "42103", "42104", "42106", "42108", "42110", "42112", "42113", "42119", "42120", "42121", "42122", "42123", "42125", "42130", "42133", "42134", "42135", "42136", "42138", "42142", "42143", "42146", "42147", "42148", "42149", "42150", "42151", "42156", "42157", "42158", "42160", "42162", "42165", "42168", "42170", "42174", "42176", "42177", "42179", "42182", "42183", "42184", "42185", "42186", "42187", "42188", "42189", "42190", "42192", "42194", "42195", "42199", "42200", "42201", "42203", "42205", "42206", "42208", "42212", "42214", "42215", "42216", "42217", "42218", "42221", "42222", "42223", "42224", "42228", "42230", "42231", "42233", "42234", "42236", "42238", "42239", "42240", "42241", "42242", "42244", "42245", "42247", "42249", "42250", "42251", "42252", "42253", "42255", "42257", "42261", "42264", "42269", "42271", "42272", "42273", "42277", "42279", "42281", "42282", "42287", "42288", "42289", "42290", "42291", "42294", "42295", "42298", "42299", "42300", "42302", "42303", "42304", "42305", "42306", "42307", "42308", "42309", "42311", "42312", "42317", "42319", "42320", "42321", "42327", "42329", "42332", "42333", "42336", "42338", "42350", "42351", "42353", "42356", "42359", "42363", "42365", "42369", "42370", "42371", "42374", "42379", "42385", "42386", "42387", "42388", "42389", "42390", "42392", "42393", "42395", "42396", "42397", "42400", "42402", "42404", "42405", "42406", "42408", "42412", "42419", "42423", "42425", "42426", "42427", "42429", "42431", "42433", "42439", "42440", "42442", "42443", "42445", "42448", "42449", "42450", "42451", "42452", "42455", "42457", "42458", "42462", "42463", "42464", "42467", "42468", "42469", "42471", "42473", "42474", "42477", "42478", "42479", "42480", "42482", "42485", "42488", "42492", "42493", "42494", "42496", "42498", "42502", "42503", "42506", "42507", "42508", "42511", "42512", "42513", "42514", "42515", "42518", "42521", "42529", "42530", "42531", "42532", "42537", "42539", "42540", "42541", "42543", "42544", "42546", "42549", "42552", "42553", "42556", "42559", "42562", "42563", "42566", "42568", "42570", "42574", "42575", "42578", "42579", "42581", "42583", "42585", "42586", "42588", "42589", "42591", "42592", "42595", "42597", "42600", "42601", "42603", "42604", "42605", "42607", "42608", "42610", "42611", "42613", "42614", "42616", "42617", "42619", "42620", "42627", "42628", "42629", "42630", "42631", "42632", "42633", "42634", "42636", "42638", "42639", "42640", "42642", "42644", "42646", "42647", "42649", "42650", "42652", "42653", "42654", "42657", "42658", "42661", "42662", "42663", "42664", "42665", "42668", "42677", "42679", "42683", "42684", "42685", "42688", "42689", "42691", "42694", "42695", "42696", "42701", "42702", "42703", "42704", "42708", "42709", "42710", "42715", "42720", "42722", "42725", "42726", "42730", "42732", "42735", "42736", "42737", "42739", "42740", "42742", "42743", "42744", "42746", "42747", "42748", "42751", "42753", "42754", "42755", "42756", "42758", "42761", "42762", "42763", "42766", "42767", "42768", "42770", "42775", "42777", "42778", "42779", "42780", "42785", "42787", "42790", "42795", "42796", "42799", "42800", "42801", "42803", "42804", "42805", "42809", "42812", "42813", "42815", "42816", "42818", "42819", "42820", "42823", "42827", "42837", "42838", "42839", "42843", "42846", "42847", "42848", "42860", "42861", "42864", "42866", "42869", "42871", "42873", "42874", "42879", "42881", "42883", "42886", "42888", "42891", "42893", "42895", "42896", "42898", "42899", "42901", "42902", "42906", "42910", "42911", "42912", "42915", "42917", "42918", "42921", "42923", "42924", "42927", "42928", "42930", "42931", "42932", "42939", "42940", "42941", "42942", "42943", "42944", "42945", "42946", "42949", "42950", "42952", "42953", "42954", "42955", "42958", "42959", "42960", "42964", "42966", "42969", "42970", "42971", "42972", "42976", "42978", "42979", "42981", "42986", "42991", "42992", "42993", "42994", "42997", "42998", "43000", "43004", "43005", "43007", "43008", "43009", "43010", "43011", "43012", "43014", "43015", "43016", "43017", "43018", "43020", "43021", "43024", "43025", "43026", "43028", "43030", "43031", "43033", "43034", "43035", "43036", "43037", "43040", "43043", "43044", "43045", "43046", "43049", "43050", "43052", "43053", "43056", "43057", "43058", "43059", "43063", "43066", "43073", "43074", "43075", "43076", "43078", "43082", "43083", "43084", "43090", "43091", "43092", "43093", "43095", "43096", "43097", "43098", "43099", "43103", "43104", "43105", "43106", "43109", "43110", "43111", "43112", "43115", "43116", "43119", "43120", "43123", "43126", "43128", "43131", "43136", "43137", "43139", "43140", "43143", "43144", "43145", "43148", "43149", "43151", "43153", "43154", "43155", "43158", "43159", "43161", "43162", "43163", "43164", "43165", "43166", "43168", "43169", "43171", "43173", "43174", "43176", "43177", "43186", "43188", "43189", "43191", "43193", "43195", "43197", "43201", "43203", "43204", "43206", "43210", "43212", "43213", "43215", "43217", "43218", "43220", "43221", "43222", "43224", "43225", "43231", "43232", "43236", "43242", "43243", "43248", "43251", "43253", "43255", "43258", "43259", "43264", "43273", "43277", "43278", "43280", "43282", "43283", "43285", "43288", "43290", "43292", "43293", "43294", "43298", "43300", "43301", "43302", "43304", "43305", "43307", "43310", "43311", "43313", "43316", "43317", "43319", "43320", "43322", "43323", "43326", "43327", "43328", "43329", "43333", "43336", "43337", "43342", "43343", "43352", "43353", "43354", "43359", "43361", "43362", "43363", "43364", "43369", "43372", "43375", "43376", "43377", "43380", "43381", "43383", "43384", "43385", "43387", "43388", "43391", "43393", "43394", "43395", "43396", "43398", "43399", "43400", "43403", "43404", "43405", "43406", "43407", "43413", "43414", "43416", "43417", "43418", "43421", "43424", "43425", "43428", "43429", "43434", "43435", "43436", "43438", "43440", "43444", "43445", "43449", "43451", "43452", "43455", "43457", "43463", "43464", "43466", "43468", "43470", "43472", "43475", "43477", "43478", "43479", "43480", "43482", "43487", "43488", "43489", "43491", "43492", "43493", "43494", "43496", "43497", "43499", "43503", "43504", "43505", "43506", "43507", "43511", "43512", "43513", "43514", "43515", "43516", "43517", "43518", "43519", "43522", "43523", "43529", "43530", "43531", "43535", "43536", "43537", "43538", "43539", "43541", "43545", "43546", "43547", "43550", "43551", "43552", "43553", "43554", "43557", "43560", "43561", "43562", "43564", "43565", "43568", "43569", "43572", "43573", "43574", "43577", "43578", "43579", "43582", "43585", "43591", "43593", "43597", "43602", "43603", "43604", "43608", "43609", "43611", "43613", "43615", "43618", "43619", "43620", "43621", "43624", "43628", "43629", "43633", "43634", "43635", "43637", "43639", "43640", "43641", "43646", "43648", "43649", "43652", "43654", "43655", "43656", "43657", "43660", "43661", "43662", "43664", "43668", "43671", "43672", "43673", "43674", "43675", "43676", "43681", "43682", "43684", "43686", "43687", "43688", "43690", "43695", "43696", "43700", "43701", "43702", "43704", "43705", "43706", "43707", "43709", "43710", "43712", "43713", "43714", "43715", "43717", "43719", "43721", "43727", "43728", "43729", "43732", "43733", "43735", "43736", "43737", "43738", "43740", "43743", "43745", "43746", "43750", "43753", "43754", "43755", "43756", "43757", "43758", "43759", "43761", "43762", "43765", "43766", "43767", "43769", "43771", "43772", "43773", "43774", "43775", "43777", "43778", "43779", "43781", "43784", "43785", "43786", "43790", "43792", "43794", "43797", "43800", "43801", "43802", "43803", "43806", "43807", "43810", "43811", "43812", "43813", "43814", "43824", "43827", "43829", "43831", "43832", "43835", "43836", "43837", "43839", "43840", "43841", "43845", "43846", "43849", "43852", "43853", "43854", "43855", "43856", "43858", "43859", "43862", "43864", "43865", "43871", "43876", "43885", "43889", "43890", "43891", "43893", "43894", "43895", "43896", "43897", "43900", "43901", "43902", "43904", "43905", "43906", "43909", "43910", "43911", "43913", "43915", "43919", "43920", "43924", "43926", "43927", "43928", "43929", "43930", "43933", "43935", "43937", "43938", "43940", "43941", "43942", "43943", "43945", "43947", "43949", "43950", "43953", "43954", "43955", "43958", "43961", "43962", "43964", "43965", "43967", "43973", "43974", "43977", "43980", "43981", "43987", "43988", "43991", "43992", "43995", "43996", "43999", "44000", "44002", "44004", "44006", "44011", "44014", "44015", "44017", "44020", "44021", "44022", "44024", "44028", "44033", "44037", "44039", "44043", "44045", "44047", "44049", "44052", "44056", "44058", "44061", "44063", "44064", "44065", "44066", "44067", "44070", "44072", "44077", "44078", "44079", "44082", "44083", "44087", "44088", "44089", "44093", "44095", "44096", "44103", "44105", "44109", "44111", "44113", "44114", "44117", "44122", "44130", "44132", "44134", "44135", "44139", "44140", "44141", "44143", "44151", "44152", "44154", "44155", "44158", "44159", "44160", "44163", "44167", "44168", "44169", "44170", "44172", "44173", "44175", "44176", "44177", "44179", "44186", "44190", "44191", "44194", "44195", "44198", "44199", "44202", "44205", "44206", "44208", "44209", "44211", "44213", "44216", "44217", "44218", "44219", "44220", "44222", "44223", "44224", "44226", "44227", "44229", "44230", "44231", "44234", "44243", "44244", "44245", "44252", "44254", "44255", "44257", "44258", "44259", "44260", "44262", "44264", "44265", "44266", "44267", "44271", "44272", "44276", "44277", "44279", "44280", "44281", "44283", "44285", "44287", "44289", "44290", "44291", "44294", "44299", "44300", "44301", "44302", "44303", "44307", "44310", "44312", "44315", "44316", "44317", "44320", "44322", "44324", "44325", "44327", "44331", "44332", "44333", "44336", "44338", "44339", "44343", "44344", "44349", "44350", "44352", "44354", "44355", "44357", "44363", "44366", "44368", "44370", "44375", "44378", "44381", "44382", "44383", "44384", "44386", "44387", "44388", "44391", "44392", "44393", "44394", "44397", "44399", "44400", "44402", "44405", "44406", "44414", "44417", "44419", "44422", "44423", "44426", "44427", "44431", "44434", "44437", "44438", "44439", "44442", "44445", "44450", "44452", "44453", "44454", "44456", "44461", "44465", "44466", "44468", "44470", "44471", "44473", "44476", "44477", "44479", "44480", "44483", "44487", "44488", "44489", "44492", "44493", "44494", "44495", "44500", "44501", "44506", "44508", "44509", "44510", "44511", "44512", "44513", "44514", "44516", "44518", "44519", "44520", "44521", "44524", "44526", "44527", "44528", "44529", "44530", "44532", "44533", "44535", "44536", "44537", "44538", "44540", "44542", "44543", "44545", "44546", "44549", "44551", "44552", "44553", "44554", "44555", "44557", "44558", "44559", "44562", "44563", "44567", "44568", "44569", "44570", "44573", "44574", "44575", "44577", "44578", "44580", "44581", "44583", "44586", "44590", "44592", "44593", "44596", "44597", "44599", "44600", "44601", "44603", "44605", "44606", "44607", "44610", "44611", "44612", "44613", "44614", "44615", "44617", "44618", "44621", "44622", "44625", "44626", "44629", "44630", "44631", "44632", "44635", "44638", "44640", "44642", "44643", "44644", "44646", "44647", "44648", "44649", "44650", "44652", "44653", "44655", "44656", "44658", "44659", "44663", "44664", "44665", "44666", "44668", "44671", "44673", "44676", "44681", "44682", "44683", "44684", "44686", "44687", "44688", "44691", "44695", "44698", "44701", "44705", "44709", "44714", "44717", "44718", "44722", "44723", "44725", "44728", "44729", "44730", "44732", "44734", "44735", "44737", "44741", "44745", "44747", "44752", "44753", "44754", "44755", "44756", "44757", "44758", "44761", "44765", "44766", "44767", "44769", "44772", "44773", "44774", "44777", "44780", "44783", "44789", "44792", "44793", "44794", "44795", "44797", "44798", "44800", "44801", "44807", "44809", "44811", "44812", "44814", "44815", "44819", "44820", "44821", "44822", "44824", "44825", "44826", "44827", "44828", "44829", "44830", "44833", "44836", "44837", "44838", "44842", "44843", "44845", "44846", "44847", "44848", "44856", "44858", "44859", "44861", "44862", "44865", "44866", "44869", "44870", "44871", "44872", "44873", "44875", "44878", "44879", "44880", "44881", "44882", "44883", "44889", "44892", "44895", "44896", "44897", "44898", "44901", "44902", "44903", "44906", "44910", "44911", "44912", "44913", "44914", "44920", "44922", "44927", "44928", "44929", "44931", "44935", "44938", "44939", "44942", "44946", "44947", "44948", "44950", "44951", "44953", "44954", "44955", "44956", "44958", "44960", "44961", "44962", "44964", "44972", "44973", "44974", "44975", "44976", "44977", "44978", "44986", "44988", "44991", "44993", "44994", "44995", "44996", "44998", "44999", "45002", "45004", "45005", "45007", "45008", "45009", "45010", "45011", "45013", "45017", "45018", "45019", "45020", "45021", "45023", "45026", "45027", "45028", "45030", "45034", "45036", "45039", "45040", "45041", "45042", "45045", "45047", "45051", "45055", "45056", "45057", "45058", "45059", "45060", "45066", "45069", "45072", "45075", "45076", "45079", "45080", "45081", "45087", "45088", "45090", "45093", "45095", "45097", "45098", "45100", "45104", "45109", "45110", "45111", "45112", "45113", "45114", "45117", "45119", "45122", "45127", "45129", "45130", "45131", "45132", "45133", "45135", "45138", "45141", "45143", "45144", "45148", "45151", "45152", "45153", "45159", "45161", "45163", "45166", "45167", "45170", "45172", "45174", "45175", "45177", "45183", "45184", "45185", "45188", "45191", "45192", "45193", "45194", "45195", "45196", "45199", "45200", "45203", "45204", "45206", "45207", "45208", "45209", "45210", "45212", "45213", "45214", "45215", "45216", "45218", "45219", "45221", "45222", "45225", "45226", "45228", "45232", "45234", "45238", "45242", "45247", "45250", "45253", "45255", "45256", "45257", "45259", "45261", "45262", "45263", "45264", "45265", "45266", "45270", "45271", "45272", "45273", "45277", "45279", "45280", "45281", "45287", "45289", "45292", "45293", "45294", "45297", "45303", "45306", "45307", "45308", "45310", "45314", "45315", "45316", "45317", "45318", "45319", "45321", "45322", "45323", "45325", "45330", "45331", "45332", "45341", "45343", "45344", "45345", "45346", "45348", "45350", "45351", "45356", "45357", "45359", "45360", "45361", "45364", "45365", "45366", "45367", "45369", "45371", "45376", "45377", "45381", "45384", "45385", "45386", "45389", "45390", "45392", "45394", "45395", "45398", "45400", "45401", "45404", "45405", "45410", "45411", "45416", "45417", "45419", "45420", "45424", "45425", "45426", "45428", "45433", "45435", "45436", "45437", "45441", "45443", "45444", "45447", "45448", "45451", "45453", "45454", "45459", "45462", "45465", "45466", "45468", "45473", "45474", "45475", "45476", "45477", "45480", "45481", "45482", "45484", "45485", "45486", "45488", "45489", "45491", "45495", "45497", "45498", "45500", "45502", "45503", "45504", "45507", "45508", "45510", "45511", "45512", "45513", "45516", "45519", "45525", "45527", "45528", "45531", "45534", "45537", "45538", "45540", "45541", "45543", "45545", "45548", "45549", "45550", "45552", "45553", "45554", "45556", "45557", "45558", "45560", "45561", "45563", "45570", "45571", "45573", "45574", "45576", "45577", "45578", "45582", "45583", "45585", "45590", "45591", "45592", "45597", "45600", "45601", "45603", "45605", "45606", "45608", "45610", "45611", "45618", "45619", "45624", "45627", "45628", "45634", "45635", "45636", "45637", "45641", "45650", "45651", "45658", "45659", "45660", "45667", "45668", "45669", "45670", "45671", "45672", "45673", "45678", "45681", "45682", "45683", "45686", "45688", "45693", "45696", "45698", "45702", "45703", "45706", "45708", "45711", "45713", "45716", "45721", "45725", "45729", "45730", "45733", "45734", "45737", "45738", "45739", "45740", "45742", "45745", "45746", "45747", "45748", "45750", "45751", "45755", "45757", "45758", "45759", "45761", "45762", "45763", "45764", "45765", "45766", "45767", "45769", "45773", "45774", "45775", "45780", "45782", "45785", "45786", "45788", "45789", "45790", "45791", "45793", "45794", "45795", "45796", "45797", "45798", "45799", "45800", "45802", "45803", "45804", "45805", "45810", "45811", "45814", "45815", "45817", "45818", "45821", "45822", "45823", "45826", "45827", "45828", "45829", "45832", "45837", "45839", "45840", "45842", "45843", "45844", "45847", "45850", "45851", "45852", "45853", "45854", "45857", "45858", "45859", "45861", "45862", "45864", "45865", "45870", "45873", "45878", "45881", "45882", "45884", "45888", "45891", "45892", "45895", "45896", "45897", "45899", "45902", "45903", "45904", "45905", "45907", "45908", "45910", "45911", "45912", "45914", "45916", "45917", "45918", "45921", "45923", "45927", "45929", "45930", "45931", "45932", "45933", "45936", "45938", "45939", "45941", "45948", "45950", "45953", "45954", "45955", "45956", "45958", "45960", "45962", "45963", "45966", "45967", "45969", "45971", "45972", "45973", "45974", "45975", "45979", "45984", "45987", "45989", "45990", "45991", "45994", "45995", "45996", "45997", "45998", "45999", "46000", "46001", "46002", "46006", "46007", "46008", "46009", "46010", "46011", "46013", "46015", "46016", "46020", "46024", "46025", "46026", "46027", "46028", "46030", "46031", "46034", "46035", "46038", "46039", "46040", "46042", "46044", "46045", "46046", "46049", "46050", "46053", "46054", "46056", "46060", "46061", "46064", "46065", "46066", "46067", "46070", "46073", "46076", "46077", "46078", "46079", "46082", "46083", "46086", "46087", "46088", "46090", "46092", "46093", "46094", "46101", "46102", "46106", "46108", "46110", "46114", "46116", "46117", "46118", "46120", "46125", "46126", "46128", "46132", "46140", "46142", "46143", "46145", "46148", "46151", "46152", "46153", "46156", "46157", "46160", "46161", "46162", "46163", "46166", "46167", "46168", "46169", "46170", "46175", "46176", "46179", "46180", "46181", "46182", "46183", "46184", "46187", "46192", "46193", "46195", "46196", "46197", "46198", "46201", "46202", "46203", "46204", "46205", "46207", "46208", "46210", "46211", "46213", "46217", "46218", "46220", "46221", "46226", "46227", "46228", "46229", "46230", "46232", "46234", "46237", "46238", "46239", "46240", "46241", "46242", "46244", "46245", "46247", "46250", "46251", "46252", "46253", "46254", "46255", "46256", "46258", "46260", "46261", "46262", "46263", "46266", "46270", "46271", "46274", "46275", "46276", "46277", "46285", "46287", "46289", "46291", "46292", "46293", "46294", "46299", "46302", "46304", "46305", "46306", "46309", "46312", "46314", "46315", "46317", "46318", "46319", "46320", "46322", "46323", "46324", "46325", "46326", "46327", "46329", "46330", "46334", "46335", "46340", "46343", "46345", "46346", "46347", "46354", "46357", "46358", "46363", "46365", "46367", "46368", "46369", "46373", "46374", "46375", "46377", "46381", "46382", "46383", "46384", "46387", "46388", "46389", "46392", "46393", "46394", "46396", "46397", "46400", "46405", "46408", "46409", "46410", "46412", "46416", "46417", "46418", "46419", "46420", "46425", "46429", "46430", "46431", "46433", "46434", "46435", "46436", "46445", "46449", "46451", "46453", "46454", "46457", "46458", "46460", "46465", "46466", "46468", "46469", "46470", "46473", "46479", "46481", "46482", "46483", "46487", "46488", "46489", "46492", "46493", "46496", "46497", "46498", "46499", "46500", "46501", "46502", "46504", "46506", "46509", "46513", "46514", "46515", "46516", "46518", "46521", "46523", "46525", "46529", "46530", "46533", "46535", "46536", "46538", "46539", "46540", "46544", "46547", "46548", "46550", "46551", "46552", "46554", "46555", "46556", "46557", "46558", "46559", "46561", "46563", "46565", "46566", "46575", "46576", "46577", "46578", "46579", "46581", "46582", "46583", "46584", "46586", "46590", "46593", "46594", "46595", "46596", "46597", "46598", "46599", "46600", "46602", "46604", "46608", "46612", "46613", "46614", "46615", "46618", "46619", "46620", "46624", "46626", "46628", "46629", "46630", "46631", "46634", "46635", "46636", "46637", "46638", "46643", "46644", "46645", "46647", "46651", "46654", "46656", "46660", "46662", "46663", "46664", "46672", "46673", "46674", "46675", "46676", "46677", "46678", "46682", "46690", "46691", "46692", "46693", "46695", "46696", "46697", "46698", "46700", "46701", "46703", "46706", "46708", "46709", "46712", "46714", "46715", "46717", "46718", "46720", "46724", "46727", "46728", "46730", "46731", "46732", "46733", "46737", "46738", "46739", "46742", "46743", "46745", "46748", "46750", "46752", "46753", "46755", "46756", "46757", "46758", "46760", "46763", "46770", "46771", "46776", "46778", "46779", "46780", "46782", "46783", "46787", "46790", "46792", "46796", "46799", "46800", "46801", "46803", "46804", "46805", "46807", "46808", "46809", "46811", "46813", "46815", "46817", "46818", "46819", "46821", "46822", "46823", "46825", "46826", "46829", "46831", "46832", "46834", "46836", "46839", "46840", "46843", "46844", "46845", "46846", "46847", "46849", "46856", "46860", "46861", "46862", "46864", "46865", "46866", "46867", "46870", "46871", "46878", "46879", "46880", "46882", "46883", "46886", "46887", "46891", "46892", "46893", "46895", "46897", "46900", "46902", "46903", "46904", "46905", "46909", "46911", "46919", "46920", "46921", "46923", "46929", "46931", "46934", "46935", "46936", "46938", "46941", "46942", "46943", "46944", "46945", "46949", "46950", "46953", "46955", "46957", "46958", "46960", "46964", "46967", "46968", "46969", "46970", "46972", "46974", "46976", "46977", "46978", "46979", "46981", "46982", "46984", "46985", "46987", "46988", "46990", "46992", "46996", "46997", "47001", "47002", "47006", "47007", "47008", "47010", "47012", "47014", "47017", "47018", "47020", "47022", "47023", "47024", "47026", "47028", "47031", "47032", "47033", "47037", "47038", "47039", "47040", "47041", "47044", "47045", "47047", "47050", "47051", "47052", "47054", "47055", "47061", "47065", "47068", "47070", "47072", "47073", "47074", "47080", "47082", "47084", "47087", "47091", "47094", "47097", "47100", "47102", "47105", "47107", "47109", "47110", "47111", "47112", "47113", "47114", "47116", "47118", "47120", "47121", "47123", "47124", "47125", "47126", "47127", "47128", "47129", "47134", "47136", "47141", "47143", "47145", "47152", "47153", "47156", "47157", "47158", "47159", "47160", "47161", "47162", "47163", "47164", "47165", "47167", "47168", "47171", "47173", "47175", "47179", "47180", "47181", "47184", "47185", "47193", "47194", "47195", "47196", "47198", "47200", "47201", "47202", "47203", "47207", "47208", "47209", "47210", "47212", "47213", "47219", "47220", "47224", "47226", "47227", "47228", "47230", "47232", "47237", "47241", "47242", "47243", "47246", "47247", "47248", "47250", "47251", "47252", "47253", "47254", "47256", "47258", "47260", "47261", "47269", "47271", "47275", "47276", "47281", "47285", "47286", "47288", "47289", "47290", "47291", "47297", "47298", "47302", "47304", "47308", "47311", "47313", "47314", "47316", "47317", "47319", "47324", "47325", "47328", "47329", "47331", "47333", "47335", "47339", "47340", "47341", "47343", "47346", "47347", "47349", "47350", "47353", "47356", "47357", "47361", "47362", "47364", "47365", "47367", "47368", "47369", "47371", "47372", "47374", "47375", "47377", "47378", "47379", "47380", "47381", "47382", "47383", "47385", "47390", "47394", "47396", "47397", "47398", "47400", "47407", "47410", "47411", "47414", "47416", "47420", "47423", "47426", "47427", "47430", "47431", "47434", "47435", "47437", "47439", "47441", "47442", "47443", "47452", "47453", "47454", "47462", "47463", "47470", "47472", "47473", "47474", "47475", "47476", "47482", "47486", "47488", "47489", "47490", "47494", "47495", "47496", "47500", "47501", "47507", "47508", "47510", "47511", "47512", "47516", "47521", "47524", "47526", "47527", "47529", "47530", "47532", "47535", "47536", "47538", "47541", "47543", "47544", "47545", "47546", "47548", "47549", "47550", "47551", "47552", "47553", "47558", "47559", "47560", "47561", "47562", "47563", "47566", "47568", "47569", "47572", "47576", "47577", "47579", "47581", "47585", "47586", "47587", "47591", "47592", "47593", "47597", "47598", "47602", "47604", "47605", "47608", "47609", "47610", "47611", "47612", "47615", "47616", "47619", "47620", "47621", "47624", "47625", "47626", "47627", "47630", "47631", "47636", "47638", "47640", "47642", "47643", "47644", "47645", "47647", "47648", "47651", "47652", "47656", "47657", "47660", "47670", "47671", "47672", "47676", "47677", "47678", "47682", "47683", "47686", "47687", "47689", "47690", "47692", "47693", "47695", "47703", "47705", "47708", "47710", "47712", "47713", "47715", "47719", "47720", "47721", "47723", "47725", "47729", "47730", "47732", "47734", "47735", "47737", "47738", "47739", "47740", "47744", "47745", "47746", "47748", "47749", "47750", "47751", "47752", "47753", "47755", "47756", "47757", "47758", "47759", "47760", "47761", "47762", "47763", "47765", "47771", "47773", "47775", "47776", "47777", "47779", "47782", "47783", "47786", "47787", "47790", "47791", "47792", "47793", "47794", "47799", "47801", "47802", "47803", "47804", "47806", "47807", "47808", "47810", "47811", "47813", "47815", "47817", "47818", "47819", "47822", "47823", "47824", "47825", "47828", "47832", "47833", "47834", "47835", "47838", "47839", "47842", "47843", "47844", "47848", "47849", "47859", "47860", "47862", "47864", "47867", "47868", "47869", "47871", "47872", "47873", "47874", "47875", "47877", "47882", "47884", "47885", "47887", "47888", "47893", "47894", "47895", "47900", "47902", "47904", "47909", "47911", "47913", "47915", "47919", "47920", "47922", "47925", "47926", "47928", "47929", "47934", "47943", "47944", "47947", "47949", "47950", "47953", "47955", "47956", "47959", "47960", "47963", "47964", "47968", "47972", "47973", "47977", "47978", "47981", "47982", "47983", "47984", "47994", "47999", "48000", "48001", "48004", "48005", "48009", "48012", "48013", "48015", "48016", "48022", "48023", "48024", "48025", "48026", "48028", "48031", "48034", "48039", "48040", "48041", "48044", "48045", "48046", "48048", "48051", "48052", "48054", "48058", "48060", "48061", "48063", "48069", "48071", "48072", "48073", "48074", "48075", "48077", "48078", "48081", "48082", "48083", "48087", "48091", "48092", "48094", "48095", "48096", "48097", "48099", "48101", "48102", "48103", "48104", "48107", "48108", "48109", "48111", "48115", "48118", "48120", "48121", "48126", "48129", "48130", "48131", "48133", "48134", "48143", "48147", "48149", "48150", "48154", "48155", "48156", "48157", "48161", "48163", "48165", "48166", "48167", "48171", "48173", "48175", "48177", "48180", "48181", "48182", "48183", "48184", "48185", "48187", "48189", "48192", "48193", "48196", "48198", "48200", "48202", "48205", "48206", "48209", "48210", "48213", "48214", "48215", "48218", "48219", "48222", "48223", "48224", "48227", "48228", "48231", "48234", "48236", "48237", "48238", "48240", "48241", "48245", "48247", "48248", "48253", "48254", "48255", "48256", "48260", "48262", "48263", "48265", "48266", "48268", "48271", "48272", "48275", "48276", "48277", "48278", "48279", "48281", "48282", "48283", "48285", "48286", "48288", "48291", "48292", "48293", "48294", "48295", "48297", "48299", "48301", "48304", "48305", "48308", "48310", "48314", "48317", "48318", "48320", "48322", "48323", "48325", "48327", "48328", "48329", "48333", "48334", "48335", "48337", "48338", "48340", "48342", "48343", "48350", "48352", "48354", "48355", "48356", "48357", "48358", "48359", "48361", "48366", "48367", "48368", "48372", "48374", "48376", "48377", "48379", "48382", "48384", "48385", "48387", "48390", "48391", "48394", "48395", "48399", "48400", "48403", "48406", "48408", "48411", "48413", "48420", "48421", "48423", "48426", "48428", "48429", "48432", "48433", "48435", "48437", "48441", "48447", "48451", "48452", "48454", "48459", "48460", "48461", "48463", "48464", "48472", "48473", "48474", "48475", "48478", "48481", "48483", "48490", "48491", "48493", "48499", "48501", "48502", "48503", "48504", "48507", "48510", "48513", "48514", "48516", "48518", "48520", "48524", "48529", "48530", "48531", "48535", "48538", "48539", "48541", "48543", "48544", "48545", "48546", "48547", "48548", "48550", "48553", "48554", "48559", "48560", "48564", "48569", "48571", "48572", "48573", "48575", "48576", "48580", "48581", "48582", "48585", "48586", "48588", "48589", "48594", "48595", "48598", "48599", "48601", "48602", "48604", "48605", "48606", "48609", "48612", "48613", "48616", "48619", "48622", "48623", "48626", "48627", "48629", "48630", "48633", "48635", "48639", "48642", "48643", "48646", "48652", "48653", "48654", "48655", "48660", "48663", "48664", "48667", "48669", "48671", "48673", "48674", "48680", "48681", "48682", "48684", "48685", "48695", "48698", "48702", "48704", "48705", "48707", "48709", "48710", "48715", "48716", "48717", "48720", "48722", "48725", "48727", "48730", "48732", "48733", "48736", "48739", "48742", "48743", "48744", "48745", "48747", "48749", "48754", "48755", "48758", "48760", "48761", "48762", "48763", "48767", "48768", "48769", "48770", "48774", "48777", "48780", "48786", "48788", "48794", "48797", "48798", "48799", "48801", "48802", "48803", "48804", "48805", "48806", "48807", "48808", "48812", "48813", "48814", "48815", "48816", "48820", "48821", "48825", "48827", "48829", "48830", "48833", "48834", "48835", "48836", "48839", "48840", "48845", "48846", "48847", "48848", "48849", "48850", "48851", "48854", "48856", "48857", "48859", "48860", "48864", "48866", "48867", "48868", "48870", "48872", "48873", "48874", "48875", "48879", "48881", "48882", "48883", "48885", "48886", "48887", "48888", "48889", "48894", "48895", "48896", "48897", "48898", "48903", "48904", "48909", "48911", "48912", "48913", "48914", "48916", "48917", "48918", "48919", "48922", "48924", "48925", "48930", "48931", "48932", "48936", "48937", "48938", "48940", "48941", "48944", "48945", "48948", "48949", "48951", "48956", "48958", "48959", "48961", "48964", "48966", "48967", "48969", "48970", "48972", "48973", "48974", "48975", "48976", "48978", "48979", "48980", "48981", "48984", "48986", "48987", "48990", "48991", "48992", "48994", "48997", "48999", "49002", "49004", "49006", "49007", "49008", "49009", "49011", "49013", "49014", "49015", "49016", "49019", "49024", "49025", "49026", "49027", "49031", "49033", "49038", "49039", "49040", "49042", "49043", "49045", "49046", "49047", "49048", "49049", "49050", "49051", "49053", "49055", "49056", "49057", "49058", "49059", "49061", "49062", "49064", "49067", "49072", "49074", "49079", "49081", "49083", "49084", "49085", "49090", "49091", "49096", "49097", "49098", "49099", "49100", "49102", "49105", "49109", "49111", "49112", "49113", "49114", "49115", "49116", "49117", "49119", "49122", "49128", "49129", "49130", "49131", "49132", "49133", "49136", "49139", "49140", "49141", "49142", "49143", "49144", "49148", "49149", "49150", "49151", "49152", "49156", "49157", "49158", "49159", "49162", "49163", "49164", "49166", "49167", "49169", "49170", "49171", "49174", "49177", "49178", "49182", "49183", "49185", "49189", "49190", "49192", "49193", "49194", "49195", "49196", "49197", "49198", "49199", "49200", "49201", "49206", "49208", "49210", "49211", "49212", "49215", "49216", "49217", "49219", "49223", "49224", "49225", "49226", "49229", "49231", "49232", "49237", "49238", "49239", "49241", "49242", "49245", "49246", "49250", "49252", "49258", "49260", "49262", "49265", "49267", "49268", "49271", "49274", "49275", "49277", "49279", "49281", "49282", "49283", "49284", "49285", "49287", "49289", "49290", "49294", "49298", "49303", "49304", "49306", "49307", "49308", "49312", "49313", "49316", "49318", "49319", "49320", "49322", "49323", "49324", "49325", "49328", "49335", "49338", "49340", "49341", "49348", "49349", "49350", "49352", "49354", "49356", "49358", "49359", "49361", "49362", "49363", "49364", "49366", "49368", "49369", "49370", "49375", "49379", "49382", "49383", "49384", "49385", "49387", "49388", "49395", "49396", "49399", "49405", "49407", "49408", "49409", "49412", "49413", "49416", "49419", "49428", "49430", "49431", "49432", "49435", "49436", "49438", "49441", "49442", "49444", "49446", "49447", "49448", "49452", "49453", "49454", "49455", "49462", "49464", "49468", "49472", "49474", "49477", "49479", "49480", "49481", "49484", "49485", "49486", "49487", "49489", "49491", "49493", "49494", "49496", "49498", "49499", "49500", "49503", "49504", "49505", "49509", "49510", "49511", "49512", "49513", "49514", "49517", "49518", "49519", "49520", "49522", "49523", "49524", "49525", "49527", "49529", "49530", "49531", "49533", "49535", "49537", "49538", "49539", "49540", "49541", "49542", "49543", "49544", "49547", "49550", "49551", "49553", "49556", "49558", "49559", "49563", "49566", "49567", "49568", "49570", "49571", "49573", "49575", "49577", "49578", "49579", "49580", "49582", "49584", "49585", "49587", "49589", "49591", "49593", "49594", "49595", "49597", "49598", "49599", "49600", "49601", "49602", "49603", "49605", "49606", "49607", "49608", "49609", "49610", "49611", "49614", "49617", "49618", "49619", "49621", "49624", "49625", "49626", "49628", "49631", "49633", "49634", "49635", "49636", "49638", "49639", "49642", "49646", "49648", "49654", "49655", "49656", "49658", "49660", "49661", "49662", "49663", "49666", "49667", "49668", "49671", "49677", "49679", "49682", "49683", "49689", "49690", "49691", "49692", "49696", "49697", "49698", "49699", "49700", "49704", "49708", "49709", "49714", "49719", "49721", "49726", "49727", "49730", "49731", "49732", "49735", "49736", "49739", "49740", "49741", "49742", "49743", "49747", "49748", "49749", "49750", "49752", "49755", "49757", "49758", "49760", "49761", "49762", "49764", "49766", "49768", "49771", "49772", "49776", "49777", "49779", "49780", "49782", "49784", "49785", "49786", "49787", "49788", "49793", "49794", "49799", "49800", "49807", "49809", "49810", "49811", "49812", "49815", "49816", "49818", "49821", "49824", "49825", "49827", "49830", "49832", "49833", "49838", "49839", "49840", "49845", "49847", "49848", "49851", "49855", "49858", "49861", "49862", "49863", "49864", "49867", "49876", "49877", "49882", "49883", "49885", "49887", "49888", "49889", "49890", "49891", "49893", "49897", "49898", "49900", "49901", "49902", "49903", "49906", "49913", "49918", "49921", "49922", "49924", "49925", "49926", "49928", "49929", "49932", "49933", "49935", "49936", "49944", "49946", "49949", "49952", "49953", "49956", "49957", "49959", "49964", "49965", "49966", "49967", "49969", "49971", "49972", "49974", "49977", "49980", "49981", "49983", "49984", "49987", "49988", "49989", "49990", "49992", "49994"]], - "valid" : ["int" , ["1", "2", "3", "4", "6", "8", "9", "10", "12", "14", "18", "19", "21", "22", "23", "25", "27", "29", "33", "35", "38", "41", "42", "44", "45", "47", "51", "54", "57", "59", "61", "62", "63", "64", "65", "67", "70", "71", "72", "73", "76", "80", "82", "83", "84", "85", "87", "89", "91", "92", "95", "98", "99", "102", "105", "108", "110", "116", "119", "121", "127", "130", "133", "138", "143", "145", "146", "149", "150", "153", "154", "157", "159", "160", "163", "176", "177", "180", "181", "182", "183", "184", "186", "187", "190", "191", "194", "198", "199", "200", "201", "202", "208", "214", "215", "218", "219", "220", "221", "222", "223", "224", "230", "232", "234", "235", "236", "237", "238", "239", "240", "242", "244", "246", "248", "249", "253", "258", "260", "261", "264", "265", "266", "267", "270", "274", "277", "279", "281", "283", "285", "286", "289", "290", "292", "293", "294", "298", "299", "304", "306", "307", "308", "309", "310", "311", "313", "314", "316", "320", "321", "324", "325", "326", "330", "331", "334", "337", "339", "342", "344", "345", "346", "348", "349", "350", "352", "353", "354", "356", "357", "358", "359", "360", "362", "363", "365", "366", "368", "373", "374", "377", "378", "379", "382", "383", "384", "385", "390", "391", "392", "393", "394", "395", "396", "401", "404", "407", "409", "410", "411", "413", "416", "417", "418", "419", "420", "421", "423", "426", "427", "428", "429", "436", "437", "441", "442", "446", "447", "448", "449", "450", "455", "458", "459", "460", "462", "463", "464", "467", "468", "470", "472", "473", "474", "475", "477", "479", "480", "481", "482", "485", "486", "488", "489", "490", "491", "492", "494", "495", "496", "499", "501", "502", "505", "509", "511", "512", "515", "517", "518", "519", "520", "521", "523", "524", "526", "528", "530", "534", "536", "537", "538", "540", "541", "542", "543", "550", "552", "555", "556", "558", "559", "560", "561", "562", "563", "566", "569", "570", "571", "574", "575", "576", "577", "580", "581", "583", "586", "587", "588", "592", "593", "594", "599", "603", "606", "607", "609", "610", "611", "613", "614", "616", "617", "618", "622", "623", "628", "630", "632", "633", "635", "636", "638", "640", "642", "644", "646", "647", "648", "651", "654", "656", "657", "658", "659", "660", "661", "662", "663", "664", "665", "667", "669", "672", "675", "678", "681", "682", "684", "685", "689", "690", "692", "693", "697", "698", "699", "701", "702", "703", "704", "706", "708", "709", "711", "712", "713", "714", "715", "718", "719", "720", "723", "725", "726", "728", "730", "733", "736", "740", "743", "744", "745", "746", "747", "749", "750", "753", "754", "755", "757", "758", "759", "762", "763", "764", "766", "767", "769", "770", "772", "773", "776", "778", "779", "780", "782", "786", "788", "792", "795", "796", "801", "802", "804", "805", "806", "808", "810", "813", "814", "818", "824", "826", "829", "830", "834", "835", "836", "839", "840", "843", "844", "845", "847", "848", "849", "850", "851", "852", "856", "858", "860", "862", "863", "865", "866", "867", "874", "875", "877", "878", "879", "880", "882", "883", "884", "886", "888", "890", "891", "892", "893", "894", "895", "898", "904", "908", "915", "916", "917", "920", "921", "924", "926", "928", "929", "930", "931", "932", "933", "936", "938", "939", "940", "941", "942", "943", "947", "949", "950", "952", "955", "956", "962", "963", "969", "971", "974", "976", "977", "982", "983", "984", "985", "989", "998", "999", "1000", "1001", "1002", "1003", "1004", "1007", "1010", "1011", "1013", "1016", "1017", "1019", "1020", "1025", "1026", "1027", "1028", "1031", "1033", "1034", "1036", "1039", "1040", "1041", "1045", "1046", "1048", "1050", "1051", "1054", "1058", "1059", "1060", "1061", "1064", "1069", "1070", "1072", "1073", "1075", "1078", "1082", "1083", "1086", "1088", "1089", "1090", "1092", "1093", "1095", "1097", "1098", "1099", "1104", "1105", "1114", "1120", "1121", "1122", "1124", "1125", "1126", "1127", "1128", "1130", "1131", "1133", "1134", "1136", "1141", "1145", "1146", "1147", "1148", "1149", "1152", "1153", "1159", "1161", "1163", "1164", "1167", "1168", "1169", "1170", "1172", "1173", "1174", "1176", "1178", "1182", "1183", "1188", "1189", "1190", "1191", "1192", "1195", "1196", "1197", "1198", "1200", "1201", "1203", "1204", "1205", "1206", "1207", "1209", "1210", "1211", "1212", "1215", "1216", "1218", "1221", "1222", "1224", "1230", "1232", "1234", "1240", "1241", "1247", "1248", "1250", "1253", "1254", "1255", "1258", "1259", "1261", "1262", "1263", "1265", "1267", "1268", "1270", "1271", "1273", "1275", "1281", "1284", "1290", "1293", "1296", "1299", "1301", "1303", "1307", "1309", "1312", "1314", "1315", "1323", "1326", "1328", "1330", "1332", "1333", "1336", "1337", "1340", "1343", "1344", "1345", "1346", "1347", "1349", "1350", "1353", "1356", "1358", "1359", "1360", "1361", "1362", "1364", "1365", "1366", "1368", "1370", "1371", "1373", "1374", "1377", "1379", "1382", "1384", "1385", "1387", "1394", "1397", "1398", "1399", "1400", "1402", "1404", "1405", "1407", "1408", "1409", "1411", "1412", "1413", "1416", "1417", "1418", "1423", "1424", "1428", "1430", "1431", "1433", "1435", "1436", "1437", "1438", "1440", "1441", "1442", "1443", "1447", "1449", "1451", "1452", "1453", "1455", "1457", "1459", "1462", "1464", "1465", "1466", "1468", "1470", "1471", "1473", "1474", "1476", "1477", "1478", "1480", "1481", "1485", "1488", "1489", "1491", "1494", "1495", "1496", "1498", "1499", "1500", "1501", "1502", "1505", "1508", "1509", "1514", "1515", "1517", "1519", "1521", "1528", "1529", "1530", "1533", "1535", "1537", "1540", "1542", "1543", "1549", "1554", "1557", "1558", "1560", "1562", "1565", "1567", "1568", "1569", "1571", "1572", "1573", "1574", "1575", "1576", "1577", "1578", "1582", "1583", "1584", "1588", "1592", "1596", "1597", "1598", "1599", "1600", "1601", "1602", "1603", "1606", "1607", "1610", "1611", "1613", "1615", "1616", "1617", "1618", "1619", "1621", "1624", "1627", "1629", "1630", "1631", "1633", "1643", "1644", "1645", "1646", "1647", "1648", "1649", "1650", "1653", "1655", "1657", "1658", "1659", "1662", "1666", "1667", "1672", "1675", "1678", "1679", "1680", "1681", "1682", "1683", "1689", "1692", "1693", "1694", "1696", "1698", "1702", "1703", "1706", "1707", "1708", "1714", "1716", "1719", "1725", "1726", "1727", "1728", "1729", "1730", "1731", "1732", "1735", "1736", "1737", "1738", "1743", "1745", "1747", "1751", "1753", "1755", "1758", "1762", "1764", "1773", "1774", "1779", "1780", "1781", "1782", "1783", "1785", "1786", "1787", "1789", "1793", "1794", "1795", "1796", "1797", "1799", "1800", "1801", "1802", "1804", "1807", "1808", "1809", "1811", "1813", "1814", "1816", "1818", "1821", "1822", "1823", "1824", "1825", "1827", "1828", "1830", "1832", "1836", "1838", "1839", "1842", "1843", "1847", "1848", "1854", "1856", "1857", "1858", "1859", "1860", "1861", "1863", "1866", "1867", "1868", "1870", "1873", "1875", "1877", "1878", "1879", "1881", "1884", "1886", "1890", "1894", "1898", "1902", "1903", "1907", "1909", "1910", "1911", "1913", "1917", "1918", "1919", "1921", "1922", "1927", "1928", "1929", "1930", "1931", "1933", "1938", "1940", "1941", "1942", "1944", "1948", "1950", "1952", "1953", "1954", "1957", "1958", "1959", "1960", "1961", "1963", "1964", "1965", "1967", "1968", "1976", "1977", "1978", "1982", "1984", "1987", "1988", "1989", "1993", "1994", "1995", "1996", "1999", "2000", "2004", "2007", "2011", "2012", "2013", "2014", "2017", "2024", "2025", "2026", "2027", "2032", "2034", "2035", "2036", "2038", "2039", "2041", "2043", "2044", "2045", "2046", "2048", "2050", "2052", "2054", "2057", "2058", "2059", "2060", "2063", "2064", "2073", "2075", "2077", "2078", "2080", "2082", "2087", "2089", "2090", "2094", "2095", "2097", "2101", "2108", "2109", "2112", "2115", "2116", "2117", "2118", "2120", "2121", "2123", "2124", "2129", "2130", "2132", "2133", "2134", "2136", "2137", "2139", "2141", "2144", "2146", "2148", "2154", "2155", "2158", "2162", "2164", "2165", "2166", "2167", "2169", "2171", "2172", "2177", "2178", "2184", "2185", "2186", "2190", "2191", "2192", "2195", "2197", "2199", "2202", "2203", "2208", "2209", "2210", "2212", "2216", "2219", "2220", "2221", "2222", "2223", "2224", "2225", "2228", "2231", "2232", "2236", "2237", "2238", "2239", "2243", "2244", "2246", "2247", "2253", "2256", "2261", "2262", "2263", "2264", "2265", "2268", "2270", "2277", "2278", "2279", "2280", "2281", "2282", "2283", "2285", "2287", "2288", "2290", "2292", "2293", "2296", "2297", "2298", "2300", "2305", "2306", "2307", "2308", "2310", "2311", "2314", "2317", "2320", "2326", "2328", "2331", "2332", "2334", "2335", "2336", "2337", "2339", "2341", "2342", "2345", "2348", "2354", "2356", "2357", "2360", "2362", "2364", "2366", "2367", "2369", "2371", "2374", "2375", "2377", "2378", "2379", "2380", "2381", "2384", "2385", "2387", "2388", "2391", "2393", "2394", "2395", "2396", "2397", "2400", "2402", "2403", "2404", "2405", "2406", "2407", "2408", "2409", "2410", "2412", "2415", "2417", "2419", "2420", "2421", "2423", "2425", "2426", "2427", "2428", "2431", "2433", "2435", "2436", "2437", "2438", "2443", "2444", "2446", "2452", "2454", "2455", "2456", "2460", "2462", "2463", "2464", "2467", "2468", "2471", "2475", "2477", "2479", "2480", "2482", "2487", "2490", "2491", "2492", "2494", "2495", "2497", "2500", "2503", "2507", "2509", "2510", "2511", "2512", "2513", "2517", "2519", "2522", "2523", "2526", "2527", "2533", "2534", "2535", "2536", "2538", "2541", "2547", "2550", "2552", "2553", "2555", "2557", "2558", "2559", "2560", "2561", "2562", "2565", "2571", "2572", "2574", "2575", "2576", "2578", "2582", "2583", "2591", "2595", "2598", "2600", "2601", "2606", "2608", "2609", "2613", "2618", "2620", "2623", "2626", "2631", "2632", "2633", "2635", "2638", "2639", "2643", "2644", "2647", "2648", "2650", "2654", "2658", "2660", "2662", "2664", "2667", "2669", "2672", "2673", "2675", "2683", "2689", "2692", "2694", "2695", "2696", "2699", "2701", "2702", "2703", "2704", "2705", "2709", "2712", "2717", "2718", "2722", "2723", "2724", "2725", "2726", "2727", "2728", "2729", "2730", "2732", "2733", "2737", "2738", "2741", "2742", "2745", "2747", "2749", "2750", "2751", "2754", "2755", "2758", "2766", "2767", "2768", "2769", "2772", "2773", "2777", "2778", "2780", "2783", "2784", "2786", "2788", "2789", "2791", "2797", "2799", "2800", "2801", "2804", "2805", "2807", "2812", "2813", "2814", "2816", "2817", "2818", "2819", "2820", "2821", "2823", "2825", "2831", "2832", "2833", "2838", "2840", "2841", "2845", "2846", "2847", "2848", "2852", "2855", "2858", "2859", "2860", "2861", "2862", "2863", "2864", "2865", "2869", "2870", "2871", "2873", "2877", "2878", "2881", "2882", "2883", "2884", "2885", "2888", "2889", "2890", "2891", "2893", "2897", "2899", "2903", "2904", "2907", "2911", "2912", "2918", "2920", "2921", "2922", "2926", "2928", "2931", "2932", "2933", "2936", "2937", "2941", "2944", "2949", "2951", "2953", "2954", "2955", "2956", "2958", "2960", "2961", "2963", "2964", "2966", "2969", "2970", "2972", "2973", "2979", "2980", "2981", "2982", "2983", "2984", "2986", "2987", "2993", "2994", "2995", "2996", "2997", "2999", "3000", "3001", "3010", "3018", "3020", "3023", "3024", "3025", "3026", "3027", "3029", "3030", "3031", "3032", "3034", "3035", "3037", "3038", "3040", "3041", "3042", "3043", "3044", "3048", "3049", "3052", "3053", "3054", "3055", "3056", "3062", "3063", "3064", "3069", "3071", "3073", "3075", "3076", "3077", "3079", "3081", "3082", "3083", "3084", "3086", "3092", "3093", "3094", "3095", "3097", "3098", "3099", "3102", "3104", "3105", "3106", "3107", "3108", "3109", "3113", "3116", "3118", "3120", "3125", "3128", "3129", "3131", "3132", "3134", "3135", "3136", "3138", "3142", "3144", "3147", "3148", "3149", "3152", "3153", "3155", "3156", "3158", "3161", "3162", "3164", "3168", "3170", "3172", "3173", "3177", "3181", "3182", "3183", "3187", "3189", "3191", "3192", "3195", "3196", "3199", "3200", "3201", "3204", "3205", "3207", "3210", "3214", "3216", "3218", "3219", "3221", "3223", "3224", "3226", "3227", "3233", "3235", "3237", "3238", "3239", "3240", "3242", "3244", "3245", "3246", "3247", "3251", "3253", "3254", "3255", "3256", "3257", "3258", "3259", "3260", "3262", "3266", "3268", "3272", "3275", "3277", "3278", "3279", "3286", "3290", "3292", "3296", "3302", "3303", "3304", "3305", "3306", "3307", "3309", "3313", "3314", "3317", "3321", "3322", "3323", "3324", "3325", "3326", "3327", "3328", "3329", "3330", "3334", "3336", "3337", "3346", "3347", "3348", "3350", "3351", "3353", "3354", "3357", "3360", "3361", "3363", "3364", "3369", "3371", "3372", "3374", "3377", "3380", "3381", "3382", "3383", "3385", "3387", "3389", "3393", "3394", "3395", "3397", "3399", "3401", "3403", "3409", "3411", "3413", "3414", "3415", "3417", "3418", "3419", "3424", "3429", "3433", "3437", "3438", "3439", "3441", "3443", "3446", "3450", "3452", "3454", "3456", "3459", "3460", "3461", "3464", "3465", "3467", "3469", "3470", "3471", "3473", "3474", "3477", "3478", "3481", "3486", "3487", "3489", "3495", "3497", "3498", "3499", "3501", "3502", "3503", "3505", "3506", "3507", "3508", "3510", "3511", "3514", "3516", "3519", "3520", "3521", "3523", "3525", "3526", "3531", "3532", "3533", "3535", "3538", "3540", "3542", "3543", "3545", "3548", "3549", "3556", "3557", "3559", "3560", "3561", "3562", "3565", "3566", "3568", "3571", "3573", "3574", "3575", "3576", "3581", "3582", "3584", "3585", "3587", "3588", "3589", "3590", "3591", "3594", "3595", "3599", "3603", "3604", "3607", "3609", "3611", "3612", "3614", "3615", "3619", "3620", "3623", "3625", "3626", "3627", "3628", "3630", "3631", "3633", "3636", "3637", "3638", "3640", "3644", "3646", "3647", "3649", "3651", "3652", "3653", "3654", "3655", "3656", "3657", "3660", "3662", "3663", "3665", "3668", "3669", "3670", "3675", "3680", "3682", "3683", "3684", "3685", "3688", "3691", "3694", "3695", "3698", "3699", "3702", "3704", "3705", "3706", "3707", "3713", "3715", "3716", "3719", "3722", "3725", "3727", "3730", "3733", "3734", "3737", "3739", "3741", "3743", "3746", "3749", "3752", "3753", "3754", "3755", "3757", "3758", "3759", "3762", "3763", "3765", "3766", "3767", "3768", "3770", "3772", "3773", "3775", "3776", "3778", "3781", "3782", "3783", "3785", "3786", "3787", "3789", "3790", "3791", "3792", "3793", "3794", "3796", "3797", "3798", "3800", "3801", "3802", "3805", "3806", "3809", "3812", "3815", "3816", "3818", "3819", "3820", "3821", "3822", "3824", "3825", "3831", "3832", "3833", "3836", "3838", "3840", "3841", "3843", "3847", "3848", "3849", "3850", "3855", "3857", "3858", "3860", "3861", "3863", "3864", "3871", "3873", "3878", "3879", "3880", "3884", "3886", "3887", "3889", "3897", "3899", "3904", "3906", "3907", "3909", "3910", "3912", "3913", "3914", "3915", "3920", "3921", "3923", "3928", "3933", "3935", "3938", "3939", "3940", "3941", "3942", "3948", "3949", "3951", "3953", "3958", "3962", "3965", "3966", "3967", "3969", "3970", "3972", "3974", "3975", "3976", "3977", "3979", "3988", "3989", "3990", "3995", "3996", "3998", "4001", "4004", "4005", "4011", "4012", "4013", "4014", "4017", "4019", "4022", "4023", "4024", "4025", "4026", "4028", "4029", "4030", "4031", "4034", "4037", "4039", "4042", "4043", "4044", "4046", "4048", "4049", "4050", "4051", "4055", "4056", "4060", "4063", "4064", "4066", "4067", "4068", "4070", "4075", "4077", "4078", "4081", "4082", "4083", "4084", "4087", "4090", "4092", "4094", "4099", "4105", "4106", "4107", "4108", "4110", "4111", "4113", "4115", "4116", "4118", "4120", "4121", "4123", "4124", "4126", "4130", "4131", "4132", "4134", "4136", "4140", "4143", "4144", "4145", "4146", "4149", "4150", "4153", "4154", "4155", "4161", "4163", "4164", "4165", "4167", "4168", "4172", "4173", "4174", "4175", "4177", "4178", "4183", "4184", "4185", "4186", "4187", "4189", "4190", "4192", "4193", "4196", "4197", "4198", "4204", "4206", "4208", "4209", "4210", "4211", "4212", "4213", "4214", "4217", "4218", "4220", "4221", "4222", "4223", "4224", "4227", "4231", "4232", "4234", "4235", "4237", "4238", "4239", "4240", "4241", "4242", "4243", "4251", "4252", "4253", "4254", "4255", "4259", "4261", "4262", "4263", "4264", "4266", "4268", "4269", "4271", "4272", "4273", "4274", "4276", "4278", "4280", "4285", "4286", "4287", "4288", "4290", "4292", "4294", "4296", "4300", "4301", "4308", "4311", "4313", "4317", "4320", "4321", "4322", "4324", "4325", "4327", "4329", "4330", "4332", "4334", "4337", "4339", "4342", "4343", "4345", "4346", "4347", "4351", "4354", "4355", "4359", "4363", "4364", "4366", "4367", "4368", "4371", "4373", "4379", "4380", "4381", "4383", "4384", "4385", "4386", "4387", "4390", "4394", "4395", "4396", "4397", "4398", "4400", "4401", "4402", "4403", "4404", "4407", "4414", "4415", "4416", "4418", "4419", "4420", "4421", "4424", "4425", "4427", "4429", "4430", "4431", "4436", "4440", "4442", "4443", "4447", "4448", "4449", "4458", "4460", "4462", "4463", "4465", "4468", "4469", "4470", "4472", "4479", "4480", "4482", "4483", "4486", "4487", "4489", "4491", "4492", "4493", "4494", "4495", "4498", "4499", "4500", "4501", "4504", "4505", "4507", "4508", "4515", "4516", "4518", "4519", "4520", "4522", "4523", "4525", "4529", "4530", "4531", "4533", "4535", "4539", "4542", "4543", "4544", "4545", "4550", "4553", "4556", "4559", "4566", "4569", "4570", "4571", "4572", "4574", "4576", "4577", "4579", "4582", "4583", "4585", "4586", "4587", "4588", "4591", "4592", "4593", "4594", "4595", "4598", "4599", "4601", "4604", "4605", "4610", "4612", "4614", "4615", "4616", "4617", "4622", "4625", "4626", "4630", "4631", "4632", "4633", "4635", "4636", "4637", "4638", "4639", "4640", "4641", "4642", "4645", "4646", "4647", "4648", "4650", "4651", "4655", "4657", "4658", "4659", "4660", "4662", "4664", "4665", "4671", "4672", "4674", "4676", "4677", "4678", "4679", "4681", "4682", "4683", "4684", "4685", "4686", "4688", "4689", "4690", "4696", "4698", "4699", "4706", "4709", "4712", "4720", "4721", "4723", "4725", "4730", "4731", "4733", "4734", "4735", "4737", "4738", "4746", "4747", "4751", "4752", "4754", "4755", "4758", "4759", "4761", "4762", "4764", "4765", "4768", "4772", "4773", "4774", "4775", "4778", "4779", "4780", "4782", "4783", "4784", "4785", "4787", "4789", "4790", "4792", "4795", "4796", "4797", "4804", "4805", "4806", "4807", "4808", "4813", "4815", "4817", "4821", "4822", "4825", "4829", "4831", "4832", "4834", "4836", "4837", "4838", "4840", "4842", "4843", "4846", "4850", "4851", "4852", "4853", "4855", "4856", "4857", "4858", "4860", "4861", "4864", "4865", "4867", "4868", "4869", "4870", "4872", "4874", "4878", "4881", "4882", "4883", "4884", "4887", "4888", "4890", "4893", "4896", "4901", "4904", "4905", "4911", "4913", "4914", "4916", "4918", "4920", "4924", "4925", "4927", "4928", "4929", "4930", "4931", "4933", "4934", "4935", "4936", "4937", "4938", "4940", "4943", "4945", "4947", "4949", "4951", "4953", "4954", "4957", "4958", "4959", "4962", "4963", "4964", "4965", "4966", "4967", "4971", "4973", "4974", "4979", "4981", "4985", "4988", "4992", "4993", "4994", "4995", "5000", "5004", "5006", "5008", "5009", "5011", "5012", "5017", "5019", "5020", "5021", "5022", "5023", "5025", "5026", "5028", "5029", "5033", "5034", "5035", "5037", "5041", "5043", "5044", "5045", "5057", "5061", "5064", "5066", "5068", "5069", "5070", "5071", "5072", "5073", "5076", "5079", "5081", "5083", "5088", "5089", "5090", "5091", "5092", "5096", "5098", "5100", "5105", "5109", "5111", "5114", "5116", "5120", "5121", "5122", "5125", "5127", "5129", "5137", "5138", "5139", "5141", "5144", "5146", "5149", "5151", "5152", "5153", "5155", "5156", "5157", "5159", "5160", "5161", "5166", "5171", "5173", "5178", "5181", "5183", "5185", "5188", "5189", "5191", "5196", "5197", "5199", "5200", "5203", "5206", "5211", "5214", "5216", "5218", "5219", "5221", "5222", "5223", "5224", "5225", "5233", "5234", "5237", "5238", "5240", "5242", "5244", "5250", "5252", "5254", "5258", "5263", "5264", "5272", "5276", "5277", "5278", "5284", "5286", "5288", "5289", "5291", "5292", "5294", "5297", "5298", "5302", "5304", "5305", "5307", "5308", "5314", "5316", "5318", "5320", "5321", "5324", "5328", "5329", "5333", "5336", "5340", "5341", "5342", "5343", "5344", "5345", "5348", "5349", "5353", "5354", "5356", "5357", "5358", "5361", "5362", "5363", "5367", "5369", "5372", "5374", "5375", "5379", "5380", "5381", "5382", "5383", "5384", "5386", "5387", "5388", "5392", "5393", "5394", "5395", "5398", "5399", "5401", "5403", "5408", "5410", "5411", "5412", "5413", "5414", "5416", "5417", "5418", "5420", "5422", "5423", "5426", "5427", "5428", "5430", "5431", "5432", "5433", "5436", "5438", "5443", "5449", "5452", "5454", "5455", "5457", "5458", "5459", "5460", "5461", "5462", "5463", "5464", "5465", "5466", "5468", "5469", "5470", "5472", "5473", "5480", "5481", "5483", "5484", "5485", "5488", "5490", "5491", "5492", "5495", "5496", "5498", "5499", "5504", "5508", "5509", "5510", "5511", "5517", "5523", "5524", "5526", "5530", "5531", "5535", "5538", "5540", "5541", "5542", "5543", "5544", "5548", "5550", "5552", "5555", "5556", "5557", "5560", "5562", "5563", "5564", "5570", "5571", "5573", "5574", "5576", "5577", "5579", "5580", "5581", "5583", "5584", "5585", "5587", "5591", "5592", "5593", "5594", "5595", "5597", "5598", "5599", "5600", "5602", "5603", "5604", "5605", "5608", "5610", "5612", "5613", "5619", "5621", "5622", "5629", "5630", "5631", "5632", "5633", "5636", "5637", "5641", "5642", "5643", "5646", "5650", "5651", "5652", "5654", "5655", "5656", "5658", "5660", "5661", "5662", "5664", "5665", "5666", "5668", "5669", "5670", "5671", "5672", "5673", "5674", "5675", "5677", "5680", "5681", "5682", "5684", "5685", "5687", "5689", "5690", "5692", "5693", "5694", "5696", "5702", "5707", "5708", "5710", "5712", "5714", "5715", "5718", "5720", "5724", "5725", "5727", "5728", "5729", "5730", "5735", "5736", "5737", "5738", "5740", "5748", "5749", "5750", "5753", "5756", "5757", "5758", "5759", "5760", "5762", "5765", "5767", "5774", "5777", "5778", "5779", "5783", "5786", "5787", "5790", "5791", "5793", "5797", "5800", "5801", "5802", "5803", "5805", "5806", "5807", "5808", "5809", "5810", "5811", "5817", "5820", "5823", "5825", "5828", "5829", "5831", "5832", "5833", "5836", "5837", "5838", "5839", "5841", "5843", "5845", "5848", "5851", "5857", "5858", "5859", "5860", "5861", "5862", "5863", "5867", "5868", "5869", "5870", "5871", "5873", "5875", "5878", "5879", "5883", "5884", "5885", "5886", "5887", "5890", "5892", "5897", "5899", "5900", "5903", "5908", "5910", "5911", "5912", "5913", "5916", "5919", "5922", "5923", "5927", "5928", "5932", "5936", "5938", "5939", "5940", "5942", "5945", "5948", "5949", "5951", "5952", "5953", "5954", "5956", "5959", "5961", "5964", "5965", "5968", "5969", "5970", "5972", "5974", "5975", "5977", "5978", "5979", "5983", "5984", "5986", "5991", "5992", "5993", "5994", "5995", "5996", "5997", "6000", "6001", "6003", "6004", "6005", "6006", "6007", "6010", "6012", "6014", "6015", "6017", "6018", "6020", "6021", "6022", "6024", "6026", "6027", "6029", "6031", "6032", "6034", "6036", "6042", "6044", "6045", "6048", "6049", "6051", "6053", "6054", "6055", "6056", "6057", "6060", "6061", "6068", "6069", "6070", "6072", "6073", "6075", "6077", "6080", "6081", "6084", "6086", "6090", "6095", "6096", "6098", "6100", "6101", "6102", "6103", "6104", "6108", "6109", "6110", "6113", "6114", "6115", "6116", "6117", "6119", "6125", "6127", "6128", "6129", "6133", "6134", "6136", "6143", "6144", "6148", "6150", "6151", "6156", "6157", "6158", "6159", "6160", "6162", "6164", "6168", "6169", "6170", "6171", "6172", "6173", "6174", "6175", "6176", "6177", "6179", "6180", "6182", "6183", "6185", "6187", "6189", "6191", "6193", "6194", "6197", "6198", "6199", "6201", "6202", "6204", "6205", "6206", "6207", "6209", "6211", "6213", "6215", "6218", "6219", "6220", "6221", "6222", "6223", "6224", "6226", "6229", "6230", "6233", "6234", "6236", "6237", "6238", "6239", "6242", "6243", "6245", "6247", "6248", "6252", "6259", "6260", "6261", "6263", "6265", "6266", "6269", "6270", "6273", "6277", "6280", "6285", "6286", "6287", "6288", "6289", "6290", "6295", "6296", "6297", "6299", "6302", "6303", "6308", "6310", "6313", "6317", "6318", "6320", "6322", "6323", "6324", "6325", "6327", "6328", "6329", "6330", "6331", "6333", "6336", "6337", "6338", "6342", "6343", "6344", "6345", "6347", "6349", "6351", "6352", "6353", "6358", "6359", "6361", "6362", "6365", "6368", "6371", "6372", "6373", "6375", "6377", "6378", "6379", "6380", "6382", "6383", "6384", "6387", "6389", "6391", "6393", "6394", "6395", "6398", "6399", "6402", "6404", "6409", "6410", "6411", "6412", "6415", "6417", "6418", "6420", "6421", "6423", "6425", "6426", "6430", "6433", "6434", "6435", "6437", "6438", "6439", "6440", "6442", "6444", "6447", "6448", "6449", "6450", "6453", "6455", "6457", "6458", "6459", "6461", "6463", "6465", "6467", "6474", "6476", "6479", "6480", "6481", "6482", "6484", "6486", "6489", "6490", "6493", "6495", "6496", "6498", "6501", "6503", "6505", "6506", "6508", "6510", "6511", "6514", "6515", "6517", "6518", "6519", "6520", "6522", "6524", "6525", "6526", "6531", "6532", "6536", "6538", "6548", "6549", "6551", "6553", "6554", "6556", "6559", "6561", "6562", "6564", "6566", "6571", "6572", "6575", "6577", "6579", "6581", "6584", "6590", "6591", "6592", "6594", "6595", "6598", "6599", "6600", "6601", "6602", "6603", "6604", "6606", "6607", "6610", "6614", "6616", "6620", "6621", "6625", "6627", "6628", "6631", "6632", "6633", "6634", "6640", "6645", "6646", "6647", "6648", "6649", "6651", "6655", "6656", "6657", "6658", "6659", "6660", "6661", "6662", "6663", "6664", "6666", "6671", "6673", "6675", "6676", "6677", "6681", "6683", "6685", "6689", "6690", "6692", "6693", "6694", "6701", "6702", "6703", "6704", "6705", "6706", "6707", "6708", "6710", "6714", "6715", "6716", "6720", "6726", "6728", "6729", "6733", "6734", "6737", "6738", "6739", "6741", "6743", "6744", "6746", "6747", "6748", "6749", "6752", "6753", "6757", "6761", "6762", "6763", "6764", "6765", "6766", "6769", "6770", "6771", "6772", "6773", "6776", "6778", "6783", "6789", "6791", "6792", "6793", "6798", "6799", "6800", "6801", "6802", "6804", "6806", "6807", "6808", "6811", "6818", "6821", "6822", "6823", "6827", "6828", "6830", "6832", "6833", "6834", "6835", "6837", "6838", "6841", "6844", "6848", "6850", "6851", "6852", "6854", "6855", "6856", "6859", "6865", "6866", "6867", "6868", "6871", "6872", "6873", "6875", "6877", "6878", "6879", "6881", "6882", "6883", "6886", "6887", "6889", "6891", "6894", "6895", "6896", "6897", "6900", "6901", "6903", "6905", "6906", "6907", "6908", "6909", "6914", "6916", "6917", "6922", "6923", "6926", "6929", "6930", "6931", "6932", "6936", "6937", "6939", "6940", "6943", "6945", "6946", "6947", "6948", "6949", "6950", "6953", "6954", "6958", "6961", "6962", "6963", "6964", "6965", "6967", "6968", "6969", "6971", "6973", "6974", "6975", "6978", "6983", "6985", "6986", "6990", "6991", "6993", "6996", "6997", "7000", "7001", "7002", "7003", "7005", "7008", "7013", "7014", "7015", "7016", "7017", "7018", "7019", "7021", "7023", "7024", "7027", "7029", "7030", "7031", "7032", "7033", "7036", "7038", "7039", "7040", "7043", "7044", "7045", "7047", "7049", "7051", "7052", "7055", "7060", "7061", "7063", "7068", "7072", "7077", "7080", "7081", "7082", "7083", "7084", "7085", "7088", "7090", "7091", "7093", "7094", "7095", "7098", "7099", "7100", "7103", "7104", "7106", "7109", "7110", "7112", "7117", "7120", "7121", "7122", "7123", "7124", "7125", "7126", "7129", "7131", "7132", "7134", "7135", "7136", "7139", "7142", "7148", "7152", "7153", "7154", "7157", "7158", "7159", "7160", "7161", "7163", "7165", "7166", "7168", "7169", "7173", "7176", "7178", "7179", "7180", "7183", "7184", "7186", "7187", "7188", "7189", "7190", "7192", "7197", "7200", "7202", "7203", "7204", "7205", "7206", "7207", "7212", "7213", "7214", "7216", "7217", "7218", "7221", "7222", "7223", "7224", "7225", "7226", "7227", "7228", "7229", "7231", "7234", "7236", "7237", "7240", "7241", "7243", "7244", "7245", "7250", "7251", "7252", "7253", "7256", "7257", "7259", "7260", "7267", "7270", "7271", "7273", "7274", "7275", "7276", "7278", "7279", "7280", "7281", "7286", "7291", "7292", "7293", "7294", "7298", "7299", "7301", "7304", "7305", "7306", "7307", "7308", "7309", "7312", "7314", "7315", "7316", "7318", "7319", "7320", "7323", "7325", "7327", "7329", "7332", "7334", "7335", "7336", "7338", "7339", "7342", "7343", "7344", "7345", "7346", "7348", "7350", "7351", "7354", "7355", "7356", "7359", "7361", "7363", "7364", "7365", "7366", "7368", "7369", "7371", "7373", "7375", "7376", "7377", "7378", "7382", "7384", "7387", "7389", "7390", "7393", "7394", "7397", "7400", "7403", "7404", "7406", "7411", "7414", "7415", "7416", "7418", "7421", "7424", "7427", "7429", "7431", "7433", "7434", "7435", "7438", "7439", "7441", "7447", "7450", "7457", "7458", "7465", "7467", "7474", "7475", "7476", "7477", "7480", "7481", "7485", "7486", "7488", "7489", "7492", "7497", "7500", "7502", "7503", "7505", "7509", "7511", "7512", "7516", "7517", "7519", "7520", "7521", "7523", "7524", "7531", "7534", "7535", "7537", "7541", "7542", "7544", "7548", "7553", "7554", "7557", "7558", "7559", "7561", "7562", "7565", "7568", "7572", "7574", "7575", "7576", "7577", "7579", "7584", "7585", "7587", "7589", "7592", "7595", "7596", "7597", "7599", "7600", "7601", "7602", "7603", "7605", "7608", "7612", "7613", "7617", "7618", "7620", "7624", "7629", "7632", "7633", "7634", "7638", "7642", "7643", "7647", "7648", "7649", "7651", "7653", "7655", "7657", "7659", "7664", "7665", "7666", "7670", "7671", "7672", "7674", "7675", "7677", "7679", "7680", "7683", "7685", "7686", "7692", "7694", "7695", "7696", "7698", "7700", "7701", "7702", "7705", "7708", "7711", "7713", "7714", "7715", "7718", "7725", "7726", "7727", "7730", "7731", "7733", "7734", "7736", "7739", "7741", "7742", "7743", "7746", "7750", "7753", "7755", "7760", "7761", "7762", "7767", "7769", "7771", "7772", "7773", "7774", "7775", "7776", "7779", "7783", "7784", "7785", "7786", "7788", "7789", "7790", "7793", "7799", "7800", "7801", "7802", "7804", "7806", "7807", "7810", "7811", "7812", "7816", "7819", "7820", "7821", "7824", "7825", "7829", "7832", "7833", "7834", "7841", "7843", "7844", "7846", "7849", "7850", "7852", "7854", "7856", "7857", "7860", "7864", "7866", "7867", "7868", "7869", "7871", "7873", "7875", "7876", "7877", "7879", "7881", "7882", "7883", "7884", "7885", "7886", "7887", "7892", "7895", "7899", "7902", "7904", "7906", "7907", "7908", "7910", "7912", "7921", "7922", "7924", "7928", "7930", "7938", "7942", "7943", "7944", "7945", "7948", "7951", "7952", "7956", "7957", "7958", "7960", "7962", "7963", "7969", "7970", "7971", "7972", "7977", "7978", "7979", "7980", "7981", "7982", "7985", "7986", "7988", "7989", "7990", "7995", "7996", "7997", "8000", "8001", "8003", "8004", "8006", "8009", "8011", "8014", "8015", "8016", "8017", "8018", "8019", "8020", "8022", "8024", "8027", "8030", "8033", "8038", "8039", "8044", "8047", "8050", "8052", "8054", "8055", "8056", "8059", "8060", "8062", "8067", "8069", "8070", "8072", "8075", "8076", "8077", "8082", "8085", "8086", "8089", "8090", "8091", "8092", "8094", "8095", "8096", "8098", "8099", "8100", "8103", "8105", "8106", "8111", "8116", "8118", "8120", "8122", "8125", "8126", "8131", "8132", "8141", "8142", "8143", "8146", "8147", "8148", "8149", "8150", "8152", "8153", "8156", "8157", "8159", "8161", "8163", "8164", "8165", "8167", "8168", "8169", "8170", "8174", "8175", "8180", "8182", "8183", "8188", "8189", "8190", "8191", "8193", "8196", "8202", "8203", "8204", "8205", "8208", "8217", "8218", "8219", "8220", "8221", "8222", "8225", "8226", "8227", "8228", "8231", "8232", "8233", "8234", "8236", "8237", "8238", "8242", "8243", "8244", "8245", "8248", "8249", "8250", "8251", "8254", "8256", "8260", "8261", "8262", "8265", "8267", "8269", "8272", "8273", "8274", "8281", "8282", "8283", "8284", "8289", "8290", "8291", "8292", "8295", "8300", "8301", "8302", "8307", "8308", "8310", "8311", "8313", "8314", "8317", "8318", "8321", "8322", "8323", "8326", "8327", "8329", "8330", "8331", "8335", "8337", "8342", "8343", "8344", "8346", "8347", "8348", "8349", "8351", "8352", "8353", "8354", "8357", "8358", "8361", "8362", "8365", "8366", "8367", "8370", "8371", "8374", "8376", "8377", "8378", "8380", "8381", "8383", "8385", "8387", "8388", "8389", "8390", "8393", "8399", "8400", "8401", "8403", "8406", "8409", "8410", "8411", "8412", "8413", "8418", "8421", "8425", "8427", "8431", "8432", "8433", "8438", "8440", "8441", "8442", "8443", "8444", "8446", "8448", "8450", "8453", "8455", "8456", "8457", "8458", "8459", "8461", "8462", "8463", "8464", "8468", "8469", "8470", "8472", "8474", "8475", "8476", "8477", "8479", "8480", "8481", "8482", "8489", "8491", "8492", "8493", "8494", "8497", "8498", "8499", "8501", "8502", "8504", "8506", "8507", "8508", "8510", "8513", "8515", "8517", "8519", "8520", "8526", "8528", "8529", "8530", "8532", "8533", "8534", "8536", "8539", "8540", "8543", "8545", "8546", "8547", "8549", "8551", "8552", "8555", "8557", "8560", "8563", "8565", "8566", "8569", "8570", "8571", "8575", "8577", "8578", "8579", "8581", "8582", "8584", "8585", "8588", "8589", "8592", "8599", "8601", "8603", "8604", "8606", "8607", "8609", "8611", "8620", "8621", "8623", "8624", "8628", "8633", "8634", "8637", "8638", "8640", "8641", "8642", "8643", "8644", "8647", "8648", "8651", "8653", "8655", "8656", "8657", "8659", "8663", "8664", "8665", "8666", "8667", "8668", "8669", "8672", "8674", "8675", "8680", "8681", "8683", "8684", "8686", "8687", "8688", "8690", "8691", "8692", "8693", "8696", "8697", "8699", "8700", "8703", "8705", "8707", "8709", "8711", "8716", "8718", "8719", "8721", "8724", "8725", "8726", "8727", "8728", "8732", "8734", "8735", "8737", "8739", "8742", "8745", "8747", "8748", "8751", "8753", "8754", "8755", "8757", "8760", "8761", "8762", "8764", "8765", "8766", "8767", "8768", "8769", "8771", "8774", "8775", "8776", "8777", "8780", "8781", "8785", "8787", "8789", "8791", "8792", "8794", "8795", "8796", "8798", "8800", "8801", "8804", "8805", "8807", "8808", "8810", "8811", "8817", "8819", "8821", "8823", "8824", "8825", "8827", "8830", "8834", "8835", "8837", "8838", "8840", "8842", "8845", "8848", "8850", "8851", "8853", "8855", "8856", "8860", "8861", "8862", "8864", "8867", "8870", "8872", "8874", "8875", "8878", "8881", "8883", "8885", "8887", "8888", "8889", "8891", "8892", "8893", "8896", "8898", "8899", "8900", "8902", "8903", "8904", "8905", "8906", "8907", "8914", "8916", "8918", "8921", "8922", "8923", "8924", "8926", "8931", "8934", "8935", "8937", "8938", "8941", "8942", "8943", "8947", "8949", "8952", "8953", "8954", "8955", "8957", "8958", "8959", "8961", "8962", "8963", "8965", "8966", "8970", "8972", "8973", "8975", "8976", "8977", "8978", "8979", "8980", "8981", "8985", "8986", "8987", "8988", "8989", "8990", "8991", "8993", "8998", "8999", "9001", "9002", "9003", "9009", "9010", "9011", "9015", "9016", "9019", "9022", "9024", "9025", "9026", "9027", "9030", "9032", "9033", "9035", "9036", "9037", "9039", "9043", "9046", "9049", "9050", "9052", "9057", "9058", "9063", "9064", "9065", "9066", "9067", "9068", "9069", "9071", "9073", "9075", "9078", "9079", "9080", "9081", "9082", "9086", "9088", "9090", "9092", "9095", "9096", "9097", "9098", "9102", "9103", "9108", "9112", "9113", "9120", "9122", "9123", "9125", "9128", "9129", "9130", "9132", "9133", "9137", "9140", "9143", "9145", "9146", "9147", "9149", "9153", "9154", "9157", "9158", "9159", "9163", "9164", "9166", "9167", "9168", "9171", "9172", "9174", "9175", "9176", "9177", "9178", "9179", "9181", "9182", "9184", "9188", "9193", "9194", "9195", "9197", "9198", "9199", "9200", "9202", "9203", "9205", "9206", "9210", "9212", "9216", "9220", "9221", "9222", "9224", "9225", "9227", "9229", "9232", "9234", "9240", "9242", "9243", "9245", "9247", "9251", "9253", "9254", "9256", "9257", "9260", "9262", "9263", "9264", "9265", "9266", "9268", "9269", "9271", "9272", "9274", "9275", "9279", "9280", "9282", "9283", "9284", "9286", "9288", "9289", "9290", "9291", "9294", "9295", "9296", "9297", "9298", "9301", "9302", "9304", "9305", "9307", "9309", "9311", "9312", "9313", "9315", "9316", "9318", "9319", "9320", "9321", "9322", "9323", "9324", "9332", "9333", "9334", "9338", "9339", "9341", "9345", "9346", "9347", "9348", "9349", "9350", "9352", "9353", "9354", "9355", "9357", "9359", "9360", "9362", "9363", "9366", "9367", "9371", "9373", "9376", "9377", "9378", "9381", "9383", "9384", "9385", "9386", "9389", "9390", "9394", "9395", "9398", "9403", "9404", "9405", "9406", "9409", "9414", "9415", "9416", "9418", "9419", "9424", "9425", "9426", "9428", "9430", "9431", "9432", "9433", "9434", "9435", "9436", "9437", "9442", "9443", "9445", "9447", "9449", "9450", "9452", "9453", "9454", "9456", "9458", "9459", "9461", "9465", "9466", "9467", "9468", "9469", "9470", "9471", "9472", "9473", "9474", "9475", "9478", "9480", "9481", "9482", "9483", "9486", "9488", "9491", "9492", "9493", "9494", "9499", "9500", "9504", "9505", "9511", "9513", "9515", "9518", "9521", "9524", "9525", "9527", "9528", "9531", "9532", "9533", "9534", "9535", "9536", "9537", "9539", "9541", "9545", "9548", "9549", "9550", "9551", "9552", "9553", "9554", "9556", "9558", "9559", "9560", "9562", "9563", "9566", "9567", "9570", "9572", "9573", "9574", "9576", "9578", "9579", "9580", "9581", "9582", "9583", "9585", "9586", "9587", "9588", "9591", "9594", "9595", "9596", "9597", "9598", "9599", "9600", "9601", "9603", "9606", "9607", "9609", "9610", "9611", "9612", "9614", "9616", "9619", "9622", "9623", "9625", "9629", "9631", "9632", "9637", "9639", "9641", "9645", "9647", "9651", "9653", "9654", "9655", "9659", "9664", "9665", "9668", "9670", "9671", "9672", "9674", "9675", "9679", "9680", "9682", "9685", "9688", "9690", "9693", "9694", "9697", "9700", "9701", "9702", "9704", "9705", "9706", "9707", "9711", "9713", "9714", "9715", "9716", "9717", "9718", "9719", "9720", "9721", "9723", "9724", "9729", "9732", "9733", "9734", "9736", "9738", "9740", "9741", "9742", "9745", "9746", "9747", "9748", "9752", "9759", "9760", "9763", "9764", "9767", "9768", "9769", "9772", "9775", "9778", "9779", "9780", "9782", "9785", "9787", "9788", "9789", "9790", "9792", "9795", "9796", "9798", "9800", "9801", "9805", "9807", "9809", "9813", "9814", "9815", "9818", "9819", "9821", "9828", "9829", "9831", "9835", "9836", "9837", "9838", "9839", "9840", "9841", "9846", "9851", "9852", "9853", "9854", "9860", "9861", "9865", "9867", "9870", "9872", "9874", "9878", "9879", "9881", "9883", "9884", "9885", "9887", "9889", "9891", "9892", "9893", "9894", "9895", "9896", "9897", "9905", "9906", "9908", "9911", "9912", "9913", "9914", "9916", "9917", "9920", "9927", "9929", "9933", "9934", "9936", "9938", "9942", "9944", "9945", "9946", "9947", "9949", "9950", "9955", "9963", "9966", "9967", "9970", "9971", "9976", "9978", "9979", "9983", "9984", "9985", "9986", "9987", "9988", "9990", "9994", "9995", "9996", "9999", "10003", "10005", "10006", "10007", "10011", "10015", "10016", "10021", "10024", "10027", "10029", "10030", "10033", "10034", "10036", "10037", "10038", "10039", "10040", "10042", "10047", "10050", "10055", "10058", "10063", "10064", "10065", "10066", "10069", "10072", "10075", "10076", "10077", "10078", "10079", "10084", "10085", "10088", "10089", "10091", "10095", "10096", "10098", "10099", "10100", "10103", "10104", "10108", "10110", "10111", "10112", "10113", "10115", "10120", "10123", "10124", "10125", "10128", "10131", "10135", "10138", "10139", "10140", "10141", "10142", "10144", "10146", "10148", "10149", "10150", "10151", "10152", "10154", "10155", "10156", "10157", "10161", "10165", "10167", "10168", "10169", "10174", "10175", "10176", "10177", "10179", "10180", "10181", "10182", "10183", "10184", "10187", "10189", "10190", "10191", "10192", "10197", "10205", "10208", "10209", "10213", "10215", "10218", "10221", "10222", "10223", "10224", "10225", "10227", "10228", "10230", "10231", "10232", "10233", "10234", "10236", "10237", "10238", "10239", "10240", "10243", "10244", "10246", "10249", "10250", "10254", "10259", "10261", "10263", "10264", "10265", "10266", "10267", "10272", "10273", "10275", "10278", "10281", "10282", "10283", "10284", "10286", "10287", "10289", "10290", "10292", "10293", "10295", "10296", "10297", "10299", "10301", "10302", "10303", "10306", "10307", "10308", "10310", "10311", "10313", "10314", "10316", "10317", "10318", "10319", "10321", "10322", "10324", "10325", "10326", "10327", "10328", "10329", "10330", "10333", "10335", "10336", "10338", "10339", "10340", "10341", "10343", "10345", "10346", "10347", "10348", "10349", "10351", "10357", "10358", "10359", "10362", "10365", "10366", "10367", "10368", "10369", "10370", "10371", "10373", "10375", "10377", "10378", "10379", "10381", "10382", "10384", "10385", "10386", "10387", "10388", "10389", "10391", "10392", "10393", "10394", "10397", "10398", "10400", "10401", "10402", "10404", "10407", "10408", "10410", "10411", "10412", "10413", "10414", "10418", "10421", "10425", "10426", "10429", "10430", "10431", "10432", "10439", "10441", "10442", "10445", "10447", "10451", "10452", "10454", "10462", "10464", "10465", "10466", "10467", "10469", "10471", "10473", "10475", "10481", "10484", "10486", "10488", "10490", "10491", "10492", "10497", "10498", "10500", "10501", "10502", "10503", "10504", "10505", "10506", "10508", "10510", "10512", "10514", "10516", "10518", "10519", "10520", "10521", "10527", "10529", "10531", "10533", "10534", "10536", "10539", "10543", "10545", "10546", "10547", "10548", "10550", "10551", "10552", "10553", "10554", "10555", "10556", "10559", "10561", "10564", "10566", "10570", "10571", "10573", "10574", "10575", "10576", "10577", "10578", "10581", "10583", "10585", "10587", "10589", "10592", "10594", "10595", "10596", "10597", "10598", "10599", "10600", "10602", "10603", "10606", "10611", "10617", "10618", "10620", "10624", "10626", "10633", "10634", "10636", "10637", "10638", "10639", "10642", "10643", "10646", "10647", "10652", "10653", "10654", "10655", "10658", "10661", "10662", "10668", "10669", "10675", "10679", "10682", "10683", "10684", "10687", "10689", "10691", "10693", "10694", "10696", "10697", "10698", "10699", "10702", "10703", "10704", "10711", "10712", "10713", "10715", "10717", "10720", "10721", "10723", "10725", "10726", "10728", "10730", "10731", "10732", "10733", "10734", "10737", "10738", "10739", "10740", "10741", "10743", "10746", "10747", "10748", "10749", "10750", "10751", "10752", "10756", "10760", "10761", "10763", "10768", "10769", "10770", "10774", "10775", "10777", "10779", "10780", "10782", "10783", "10784", "10785", "10787", "10789", "10790", "10796", "10797", "10799", "10800", "10801", "10804", "10808", "10809", "10812", "10817", "10823", "10825", "10828", "10830", "10831", "10836", "10837", "10839", "10840", "10843", "10844", "10845", "10847", "10850", "10853", "10854", "10857", "10858", "10861", "10862", "10863", "10866", "10868", "10869", "10871", "10872", "10873", "10875", "10876", "10878", "10880", "10888", "10891", "10892", "10894", "10895", "10896", "10897", "10903", "10905", "10906", "10907", "10908", "10909", "10912", "10913", "10916", "10917", "10918", "10923", "10925", "10926", "10927", "10929", "10931", "10933", "10934", "10936", "10940", "10941", "10943", "10944", "10945", "10948", "10951", "10953", "10954", "10957", "10961", "10962", "10967", "10968", "10969", "10970", "10974", "10975", "10980", "10982", "10983", "10984", "10986", "10988", "10990", "10991", "10992", "10995", "11002", "11003", "11006", "11007", "11008", "11010", "11013", "11014", "11015", "11016", "11017", "11018", "11020", "11024", "11027", "11029", "11030", "11033", "11036", "11037", "11040", "11041", "11046", "11050", "11052", "11053", "11054", "11055", "11056", "11057", "11060", "11061", "11062", "11063", "11064", "11070", "11071", "11072", "11073", "11075", "11076", "11077", "11078", "11079", "11082", "11084", "11085", "11087", "11088", "11089", "11095", "11096", "11097", "11099", "11102", "11103", "11108", "11109", "11110", "11112", "11113", "11114", "11116", "11117", "11118", "11121", "11122", "11123", "11125", "11126", "11127", "11129", "11131", "11132", "11133", "11137", "11139", "11155", "11156", "11158", "11164", "11165", "11166", "11170", "11173", "11175", "11176", "11178", "11179", "11180", "11182", "11183", "11186", "11187", "11188", "11189", "11190", "11191", "11193", "11194", "11196", "11197", "11198", "11199", "11201", "11203", "11206", "11207", "11208", "11211", "11213", "11214", "11215", "11216", "11219", "11220", "11223", "11224", "11229", "11231", "11234", "11235", "11236", "11237", "11240", "11241", "11242", "11244", "11245", "11246", "11247", "11249", "11250", "11256", "11258", "11261", "11262", "11263", "11265", "11266", "11268", "11269", "11271", "11273", "11274", "11275", "11277", "11282", "11286", "11288", "11289", "11290", "11292", "11293", "11295", "11297", "11299", "11302", "11308", "11314", "11315", "11316", "11317", "11319", "11320", "11321", "11323", "11326", "11327", "11328", "11329", "11330", "11331", "11335", "11337", "11338", "11340", "11341", "11342", "11345", "11349", "11350", "11351", "11352", "11355", "11358", "11360", "11361", "11363", "11370", "11372", "11373", "11374", "11375", "11379", "11386", "11387", "11389", "11392", "11393", "11394", "11396", "11398", "11399", "11400", "11401", "11402", "11404", "11410", "11411", "11416", "11419", "11422", "11424", "11426", "11429", "11430", "11433", "11434", "11435", "11437", "11438", "11440", "11442", "11444", "11445", "11447", "11448", "11450", "11451", "11453", "11455", "11457", "11458", "11460", "11463", "11464", "11474", "11475", "11476", "11480", "11481", "11482", "11483", "11485", "11487", "11488", "11492", "11498", "11503", "11504", "11506", "11507", "11510", "11511", "11515", "11517", "11520", "11523", "11525", "11527", "11532", "11534", "11535", "11537", "11541", "11544", "11545", "11551", "11552", "11555", "11556", "11557", "11559", "11560", "11564", "11565", "11566", "11570", "11574", "11581", "11585", "11587", "11588", "11589", "11590", "11592", "11593", "11594", "11595", "11597", "11599", "11601", "11603", "11607", "11608", "11610", "11611", "11613", "11614", "11616", "11618", "11623", "11627", "11629", "11630", "11632", "11633", "11634", "11635", "11637", "11647", "11650", "11651", "11652", "11656", "11657", "11658", "11662", "11666", "11667", "11670", "11675", "11676", "11677", "11680", "11683", "11685", "11687", "11689", "11690", "11692", "11694", "11696", "11697", "11699", "11700", "11704", "11705", "11706", "11707", "11711", "11712", "11713", "11714", "11715", "11716", "11717", "11719", "11724", "11725", "11729", "11731", "11732", "11733", "11740", "11745", "11746", "11748", "11751", "11753", "11758", "11759", "11762", "11764", "11765", "11766", "11767", "11769", "11771", "11773", "11775", "11777", "11779", "11780", "11781", "11782", "11783", "11785", "11786", "11788", "11789", "11791", "11793", "11795", "11796", "11797", "11800", "11805", "11806", "11807", "11808", "11812", "11813", "11814", "11815", "11818", "11819", "11820", "11821", "11825", "11826", "11832", "11833", "11834", "11835", "11837", "11838", "11839", "11841", "11842", "11844", "11846", "11847", "11849", "11850", "11852", "11855", "11856", "11860", "11861", "11862", "11864", "11866", "11867", "11868", "11871", "11872", "11876", "11877", "11878", "11879", "11881", "11886", "11888", "11889", "11891", "11893", "11895", "11897", "11898", "11899", "11902", "11903", "11908", "11910", "11913", "11914", "11917", "11918", "11919", "11922", "11923", "11924", "11925", "11930", "11932", "11933", "11934", "11936", "11937", "11939", "11941", "11942", "11943", "11944", "11946", "11948", "11949", "11950", "11951", "11953", "11955", "11956", "11959", "11960", "11963", "11966", "11967", "11970", "11971", "11972", "11973", "11974", "11976", "11978", "11979", "11983", "11984", "11986", "11987", "11992", "11993", "11994", "11996", "11997", "11999", "12004", "12005", "12006", "12007", "12008", "12009", "12013", "12014", "12020", "12021", "12022", "12023", "12026", "12030", "12031", "12033", "12034", "12035", "12037", "12038", "12044", "12045", "12047", "12048", "12052", "12054", "12055", "12061", "12063", "12065", "12066", "12067", "12068", "12069", "12070", "12071", "12076", "12078", "12081", "12083", "12085", "12088", "12089", "12090", "12092", "12093", "12100", "12102", "12103", "12104", "12105", "12109", "12110", "12111", "12112", "12113", "12115", "12121", "12122", "12123", "12124", "12137", "12141", "12142", "12144", "12147", "12149", "12151", "12154", "12155", "12156", "12158", "12159", "12160", "12161", "12163", "12165", "12168", "12171", "12174", "12175", "12176", "12177", "12183", "12186", "12188", "12189", "12191", "12196", "12199", "12200", "12201", "12204", "12205", "12207", "12208", "12212", "12214", "12215", "12216", "12217", "12218", "12219", "12220", "12223", "12226", "12228", "12229", "12231", "12232", "12239", "12241", "12245", "12247", "12248", "12252", "12255", "12259", "12261", "12262", "12263", "12265", "12266", "12267", "12268", "12278", "12280", "12283", "12287", "12289", "12290", "12291", "12292", "12294", "12295", "12297", "12300", "12302", "12303", "12304", "12305", "12309", "12310", "12311", "12312", "12313", "12317", "12318", "12320", "12322", "12324", "12326", "12328", "12330", "12331", "12332", "12334", "12335", "12338", "12340", "12343", "12344", "12345", "12347", "12349", "12351", "12355", "12361", "12362", "12363", "12366", "12368", "12369", "12372", "12373", "12376", "12378", "12380", "12381", "12383", "12387", "12388", "12389", "12390", "12391", "12394", "12397", "12399", "12403", "12404", "12405", "12406", "12407", "12408", "12409", "12410", "12412", "12413", "12414", "12415", "12417", "12420", "12422", "12423", "12424", "12426", "12427", "12432", "12433", "12434", "12435", "12436", "12437", "12438", "12439", "12440", "12442", "12444", "12448", "12449", "12455", "12458", "12460", "12461", "12462", "12464", "12465", "12466", "12470", "12477", "12478", "12481", "12483", "12489", "12491", "12492", "12493", "12494", "12496", "12497", "12500", "12503", "12504", "12505", "12506", "12507", "12508", "12509", "12510", "12512", "12514", "12515", "12516", "12518", "12519", "12521", "12522", "12524", "12525", "12529", "12536", "12537", "12538", "12542", "12543", "12545", "12546", "12548", "12550", "12552", "12554", "12556", "12557", "12562", "12563", "12565", "12566", "12567", "12570", "12572", "12573", "12574", "12575", "12576", "12580", "12581", "12582", "12583", "12586", "12593", "12594", "12595", "12597", "12598", "12599", "12600", "12602", "12605", "12607", "12608", "12609", "12612", "12613", "12617", "12618", "12620", "12622", "12623", "12625", "12626", "12627", "12628", "12630", "12631", "12634", "12636", "12638", "12640", "12643", "12650", "12653", "12654", "12656", "12657", "12658", "12660", "12662", "12664", "12668", "12669", "12671", "12676", "12678", "12680", "12682", "12683", "12686", "12688", "12690", "12693", "12694", "12695", "12697", "12698", "12701", "12703", "12706", "12708", "12709", "12711", "12714", "12719", "12721", "12723", "12724", "12725", "12726", "12727", "12732", "12734", "12735", "12736", "12737", "12738", "12741", "12742", "12743", "12748", "12750", "12753", "12754", "12755", "12756", "12757", "12759", "12760", "12762", "12763", "12764", "12766", "12768", "12773", "12774", "12775", "12776", "12777", "12778", "12781", "12783", "12784", "12785", "12786", "12788", "12790", "12792", "12794", "12797", "12807", "12810", "12814", "12815", "12818", "12819", "12820", "12822", "12826", "12827", "12828", "12829", "12833", "12835", "12836", "12838", "12840", "12841", "12842", "12848", "12849", "12851", "12852", "12854", "12855", "12856", "12857", "12858", "12859", "12860", "12862", "12866", "12868", "12871", "12873", "12874", "12875", "12876", "12877", "12881", "12884", "12892", "12895", "12896", "12899", "12900", "12901", "12902", "12903", "12904", "12906", "12907", "12915", "12916", "12917", "12920", "12921", "12922", "12923", "12927", "12934", "12938", "12941", "12945", "12947", "12948", "12949", "12953", "12955", "12956", "12958", "12961", "12963", "12964", "12967", "12968", "12971", "12972", "12973", "12979", "12980", "12984", "12990", "12991", "12993", "12994", "12995", "12998", "12999", "13000", "13002", "13005", "13006", "13007", "13009", "13013", "13014", "13016", "13020", "13021", "13022", "13029", "13031", "13032", "13034", "13035", "13036", "13040", "13043", "13044", "13049", "13050", "13051", "13053", "13054", "13059", "13061", "13064", "13065", "13068", "13069", "13070", "13072", "13073", "13074", "13075", "13077", "13082", "13086", "13091", "13092", "13093", "13094", "13098", "13099", "13102", "13103", "13105", "13106", "13109", "13110", "13113", "13119", "13120", "13121", "13122", "13123", "13125", "13128", "13129", "13130", "13132", "13135", "13136", "13138", "13139", "13140", "13141", "13144", "13145", "13150", "13153", "13154", "13156", "13157", "13159", "13161", "13165", "13166", "13167", "13170", "13173", "13177", "13178", "13179", "13180", "13183", "13188", "13191", "13192", "13194", "13197", "13198", "13199", "13203", "13204", "13205", "13210", "13213", "13215", "13216", "13218", "13219", "13222", "13223", "13225", "13226", "13228", "13229", "13230", "13233", "13234", "13235", "13236", "13239", "13241", "13242", "13245", "13246", "13248", "13251", "13253", "13255", "13257", "13260", "13261", "13262", "13263", "13264", "13265", "13268", "13271", "13272", "13273", "13275", "13281", "13282", "13283", "13285", "13287", "13291", "13294", "13298", "13299", "13302", "13304", "13305", "13306", "13309", "13311", "13312", "13314", "13315", "13316", "13319", "13320", "13322", "13323", "13325", "13326", "13327", "13329", "13332", "13333", "13335", "13336", "13340", "13342", "13343", "13344", "13345", "13348", "13350", "13352", "13353", "13354", "13355", "13356", "13357", "13359", "13360", "13363", "13364", "13365", "13366", "13367", "13368", "13369", "13373", "13375", "13380", "13383", "13385", "13389", "13393", "13397", "13398", "13400", "13401", "13403", "13404", "13405", "13406", "13409", "13411", "13412", "13413", "13414", "13415", "13418", "13420", "13421", "13423", "13428", "13440", "13443", "13444", "13446", "13447", "13453", "13457", "13459", "13461", "13464", "13465", "13466", "13467", "13468", "13469", "13470", "13471", "13478", "13479", "13487", "13490", "13491", "13494", "13497", "13498", "13505", "13508", "13510", "13512", "13513", "13515", "13516", "13517", "13518", "13520", "13524", "13525", "13531", "13532", "13533", "13534", "13535", "13536", "13541", "13542", "13546", "13547", "13548", "13549", "13550", "13554", "13555", "13556", "13559", "13562", "13563", "13564", "13577", "13578", "13579", "13580", "13581", "13582", "13583", "13584", "13585", "13588", "13591", "13593", "13597", "13598", "13603", "13605", "13606", "13607", "13608", "13609", "13611", "13612", "13613", "13614", "13616", "13617", "13618", "13619", "13620", "13621", "13622", "13624", "13625", "13630", "13632", "13633", "13636", "13644", "13647", "13648", "13649", "13651", "13652", "13655", "13659", "13662", "13663", "13668", "13669", "13670", "13671", "13676", "13677", "13678", "13679", "13681", "13684", "13687", "13688", "13689", "13691", "13693", "13694", "13696", "13697", "13699", "13700", "13701", "13703", "13705", "13706", "13707", "13708", "13709", "13711", "13713", "13717", "13719", "13721", "13724", "13725", "13727", "13728", "13729", "13736", "13737", "13738", "13739", "13740", "13741", "13742", "13743", "13746", "13749", "13750", "13752", "13753", "13754", "13755", "13757", "13760", "13764", "13765", "13766", "13767", "13771", "13772", "13773", "13775", "13776", "13780", "13781", "13782", "13783", "13784", "13787", "13793", "13794", "13796", "13797", "13798", "13799", "13801", "13802", "13804", "13806", "13807", "13809", "13810", "13814", "13815", "13816", "13817", "13818", "13820", "13823", "13825", "13827", "13829", "13833", "13838", "13839", "13840", "13841", "13842", "13844", "13845", "13850", "13851", "13852", "13855", "13856", "13858", "13859", "13860", "13862", "13863", "13864", "13865", "13867", "13869", "13872", "13873", "13874", "13876", "13880", "13881", "13882", "13883", "13884", "13886", "13887", "13888", "13890", "13891", "13897", "13900", "13901", "13902", "13903", "13905", "13906", "13909", "13912", "13913", "13914", "13919", "13920", "13921", "13923", "13926", "13929", "13931", "13933", "13934", "13935", "13937", "13938", "13939", "13941", "13943", "13945", "13947", "13950", "13951", "13952", "13954", "13955", "13957", "13958", "13959", "13963", "13964", "13966", "13968", "13969", "13970", "13971", "13972", "13974", "13975", "13979", "13981", "13982", "13983", "13985", "13986", "13987", "13989", "13991", "13992", "13996", "13998", "14000", "14002", "14003", "14006", "14007", "14009", "14012", "14015", "14017", "14019", "14022", "14023", "14027", "14028", "14029", "14032", "14033", "14034", "14036", "14038", "14039", "14041", "14046", "14047", "14050", "14052", "14054", "14055", "14057", "14058", "14059", "14064", "14066", "14067", "14070", "14077", "14078", "14079", "14081", "14082", "14083", "14084", "14086", "14091", "14092", "14093", "14094", "14097", "14101", "14102", "14103", "14105", "14107", "14109", "14110", "14111", "14114", "14115", "14116", "14118", "14119", "14124", "14126", "14129", "14131", "14135", "14136", "14137", "14138", "14140", "14142", "14143", "14144", "14146", "14147", "14150", "14152", "14153", "14154", "14155", "14156", "14157", "14162", "14163", "14165", "14166", "14167", "14168", "14172", "14175", "14176", "14180", "14181", "14183", "14184", "14185", "14189", "14191", "14193", "14194", "14195", "14196", "14197", "14198", "14199", "14200", "14202", "14203", "14205", "14206", "14207", "14209", "14210", "14211", "14212", "14213", "14215", "14216", "14217", "14219", "14221", "14222", "14230", "14232", "14234", "14237", "14239", "14241", "14242", "14244", "14247", "14248", "14252", "14254", "14256", "14257", "14259", "14262", "14263", "14264", "14267", "14269", "14271", "14272", "14277", "14281", "14283", "14284", "14285", "14287", "14288", "14290", "14291", "14292", "14294", "14297", "14301", "14303", "14304", "14305", "14306", "14307", "14309", "14313", "14315", "14318", "14320", "14322", "14323", "14324", "14325", "14333", "14334", "14335", "14339", "14342", "14343", "14346", "14347", "14348", "14350", "14351", "14354", "14360", "14363", "14370", "14375", "14377", "14378", "14379", "14381", "14383", "14384", "14387", "14389", "14390", "14392", "14395", "14397", "14398", "14400", "14401", "14403", "14404", "14405", "14407", "14408", "14409", "14410", "14415", "14416", "14417", "14419", "14420", "14421", "14423", "14424", "14427", "14429", "14430", "14431", "14432", "14434", "14436", "14438", "14442", "14446", "14447", "14450", "14451", "14452", "14454", "14464", "14473", "14477", "14479", "14480", "14481", "14482", "14483", "14484", "14486", "14488", "14491", "14495", "14496", "14498", "14503", "14504", "14505", "14506", "14509", "14524", "14525", "14532", "14533", "14537", "14541", "14545", "14546", "14547", "14548", "14549", "14550", "14556", "14562", "14566", "14567", "14570", "14571", "14572", "14576", "14577", "14579", "14582", "14584", "14585", "14586", "14587", "14588", "14590", "14595", "14596", "14597", "14598", "14600", "14601", "14602", "14605", "14612", "14613", "14616", "14619", "14620", "14623", "14624", "14628", "14630", "14637", "14641", "14642", "14643", "14645", "14646", "14647", "14649", "14652", "14654", "14656", "14660", "14663", "14665", "14669", "14670", "14671", "14673", "14674", "14675", "14676", "14677", "14678", "14680", "14681", "14682", "14685", "14687", "14689", "14691", "14692", "14693", "14698", "14702", "14703", "14704", "14705", "14707", "14711", "14713", "14715", "14717", "14718", "14719", "14720", "14724", "14729", "14730", "14731", "14732", "14745", "14746", "14749", "14751", "14753", "14754", "14755", "14757", "14758", "14759", "14763", "14766", "14767", "14769", "14770", "14774", "14775", "14779", "14785", "14787", "14788", "14789", "14790", "14792", "14795", "14796", "14797", "14798", "14799", "14800", "14803", "14806", "14807", "14808", "14809", "14811", "14818", "14820", "14821", "14823", "14826", "14829", "14833", "14835", "14836", "14838", "14839", "14840", "14841", "14843", "14845", "14846", "14849", "14852", "14855", "14856", "14857", "14858", "14860", "14861", "14863", "14865", "14868", "14870", "14871", "14872", "14873", "14875", "14877", "14879", "14881", "14888", "14890", "14892", "14893", "14894", "14896", "14901", "14902", "14903", "14904", "14906", "14907", "14909", "14910", "14911", "14913", "14915", "14918", "14919", "14921", "14922", "14923", "14924", "14927", "14929", "14931", "14932", "14934", "14935", "14937", "14938", "14940", "14944", "14946", "14950", "14951", "14952", "14953", "14956", "14958", "14959", "14962", "14964", "14967", "14969", "14970", "14972", "14973", "14974", "14975", "14976", "14977", "14978", "14981", "14982", "14983", "14985", "14989", "14991", "14992", "14993", "14994", "14995", "14997", "14998", "14999", "15000", "15002", "15005", "15006", "15007", "15008", "15010", "15013", "15015", "15018", "15019", "15020", "15022", "15023", "15026", "15031", "15032", "15035", "15039", "15043", "15045", "15048", "15050", "15051", "15055", "15056", "15057", "15058", "15060", "15063", "15071", "15072", "15074", "15076", "15077", "15078", "15079", "15080", "15082", "15084", "15085", "15086", "15087", "15089", "15090", "15092", "15094", "15096", "15099", "15101", "15102", "15108", "15109", "15114", "15116", "15117", "15118", "15119", "15120", "15121", "15122", "15125", "15127", "15128", "15138", "15139", "15140", "15142", "15146", "15148", "15150", "15154", "15164", "15165", "15168", "15171", "15172", "15174", "15180", "15183", "15185", "15187", "15188", "15189", "15192", "15193", "15194", "15197", "15199", "15202", "15203", "15205", "15210", "15214", "15215", "15219", "15221", "15224", "15225", "15226", "15227", "15231", "15234", "15235", "15239", "15240", "15241", "15243", "15246", "15247", "15248", "15252", "15254", "15256", "15257", "15258", "15259", "15262", "15263", "15266", "15272", "15274", "15275", "15278", "15280", "15282", "15284", "15290", "15293", "15295", "15296", "15297", "15298", "15299", "15300", "15303", "15304", "15306", "15307", "15309", "15310", "15311", "15312", "15315", "15320", "15324", "15331", "15333", "15337", "15340", "15342", "15344", "15345", "15347", "15348", "15350", "15351", "15352", "15353", "15355", "15359", "15360", "15361", "15363", "15364", "15365", "15366", "15368", "15369", "15371", "15372", "15373", "15375", "15377", "15378", "15380", "15381", "15383", "15384", "15385", "15386", "15389", "15390", "15395", "15396", "15398", "15400", "15402", "15403", "15404", "15406", "15408", "15409", "15411", "15414", "15415", "15418", "15423", "15425", "15428", "15430", "15432", "15434", "15435", "15438", "15439", "15440", "15441", "15443", "15445", "15446", "15447", "15449", "15450", "15455", "15456", "15457", "15462", "15463", "15465", "15467", "15468", "15470", "15471", "15473", "15477", "15478", "15480", "15481", "15482", "15484", "15485", "15489", "15493", "15497", "15498", "15499", "15500", "15502", "15505", "15509", "15512", "15519", "15521", "15523", "15524", "15526", "15530", "15531", "15536", "15537", "15539", "15540", "15542", "15544", "15546", "15548", "15550", "15556", "15558", "15560", "15561", "15563", "15569", "15570", "15572", "15574", "15575", "15576", "15577", "15578", "15583", "15584", "15588", "15590", "15592", "15593", "15594", "15595", "15598", "15602", "15603", "15606", "15608", "15611", "15612", "15615", "15616", "15617", "15618", "15621", "15622", "15623", "15626", "15627", "15628", "15629", "15631", "15634", "15635", "15638", "15640", "15641", "15643", "15644", "15648", "15651", "15653", "15654", "15656", "15659", "15662", "15663", "15665", "15667", "15668", "15669", "15672", "15673", "15677", "15678", "15680", "15683", "15684", "15687", "15689", "15690", "15695", "15696", "15697", "15698", "15699", "15701", "15702", "15704", "15705", "15710", "15711", "15716", "15717", "15721", "15722", "15723", "15725", "15726", "15727", "15728", "15729", "15731", "15733", "15734", "15736", "15738", "15742", "15743", "15744", "15745", "15746", "15750", "15751", "15752", "15755", "15757", "15758", "15759", "15762", "15765", "15769", "15770", "15773", "15774", "15775", "15776", "15777", "15778", "15780", "15782", "15789", "15790", "15791", "15792", "15793", "15795", "15799", "15801", "15804", "15805", "15808", "15809", "15810", "15811", "15812", "15814", "15816", "15818", "15819", "15820", "15821", "15822", "15825", "15828", "15829", "15830", "15834", "15835", "15838", "15840", "15842", "15843", "15845", "15848", "15851", "15853", "15855", "15860", "15863", "15865", "15868", "15869", "15871", "15872", "15873", "15874", "15879", "15881", "15883", "15885", "15886", "15888", "15889", "15891", "15894", "15896", "15899", "15905", "15910", "15911", "15912", "15917", "15919", "15920", "15921", "15929", "15930", "15933", "15935", "15942", "15943", "15944", "15945", "15946", "15951", "15954", "15957", "15958", "15962", "15964", "15966", "15967", "15968", "15969", "15971", "15972", "15977", "15981", "15982", "15984", "15985", "15987", "15988", "15990", "15994", "15996", "15999", "16000", "16004", "16006", "16007", "16011", "16014", "16015", "16017", "16019", "16022", "16026", "16028", "16029", "16032", "16035", "16036", "16038", "16041", "16046", "16051", "16054", "16059", "16060", "16062", "16064", "16067", "16069", "16073", "16074", "16076", "16077", "16079", "16083", "16084", "16087", "16088", "16092", "16093", "16094", "16095", "16098", "16099", "16102", "16103", "16104", "16105", "16107", "16109", "16111", "16113", "16117", "16118", "16119", "16120", "16122", "16126", "16129", "16131", "16132", "16133", "16135", "16138", "16141", "16144", "16146", "16149", "16150", "16153", "16159", "16160", "16161", "16164", "16165", "16166", "16171", "16173", "16174", "16176", "16177", "16179", "16182", "16184", "16187", "16190", "16193", "16195", "16196", "16198", "16200", "16202", "16203", "16205", "16207", "16212", "16213", "16214", "16217", "16220", "16221", "16222", "16223", "16224", "16226", "16229", "16230", "16231", "16233", "16236", "16238", "16241", "16242", "16244", "16245", "16246", "16247", "16250", "16252", "16253", "16255", "16257", "16258", "16260", "16261", "16265", "16267", "16268", "16272", "16277", "16280", "16281", "16283", "16284", "16286", "16288", "16290", "16295", "16296", "16297", "16298", "16301", "16302", "16305", "16307", "16317", "16319", "16324", "16327", "16328", "16330", "16331", "16332", "16336", "16337", "16338", "16342", "16343", "16345", "16354", "16355", "16356", "16358", "16361", "16366", "16368", "16369", "16370", "16371", "16372", "16377", "16379", "16380", "16381", "16384", "16389", "16390", "16391", "16392", "16393", "16394", "16395", "16396", "16399", "16400", "16404", "16405", "16407", "16409", "16410", "16411", "16414", "16418", "16422", "16425", "16426", "16427", "16428", "16430", "16432", "16434", "16435", "16436", "16437", "16438", "16442", "16444", "16445", "16446", "16447", "16449", "16450", "16451", "16456", "16458", "16461", "16464", "16466", "16473", "16480", "16481", "16482", "16483", "16484", "16486", "16487", "16489", "16490", "16491", "16492", "16494", "16495", "16497", "16498", "16501", "16502", "16504", "16507", "16508", "16509", "16511", "16513", "16514", "16516", "16518", "16519", "16520", "16521", "16525", "16529", "16533", "16539", "16540", "16542", "16543", "16547", "16549", "16551", "16554", "16557", "16560", "16561", "16562", "16564", "16566", "16568", "16570", "16571", "16572", "16573", "16578", "16582", "16583", "16586", "16587", "16589", "16590", "16593", "16595", "16598", "16602", "16603", "16607", "16608", "16609", "16614", "16619", "16620", "16621", "16622", "16623", "16625", "16628", "16629", "16630", "16632", "16637", "16638", "16639", "16641", "16643", "16644", "16645", "16646", "16647", "16649", "16650", "16652", "16654", "16661", "16662", "16665", "16669", "16671", "16672", "16673", "16678", "16679", "16680", "16682", "16684", "16685", "16686", "16688", "16690", "16695", "16697", "16698", "16703", "16705", "16707", "16708", "16709", "16717", "16718", "16719", "16721", "16722", "16723", "16726", "16728", "16731", "16732", "16733", "16737", "16738", "16739", "16740", "16741", "16742", "16743", "16744", "16746", "16747", "16748", "16750", "16751", "16752", "16753", "16754", "16756", "16757", "16758", "16759", "16762", "16763", "16765", "16766", "16770", "16771", "16774", "16776", "16779", "16783", "16788", "16790", "16791", "16792", "16793", "16794", "16796", "16797", "16798", "16800", "16804", "16805", "16808", "16809", "16811", "16812", "16813", "16814", "16815", "16817", "16818", "16823", "16826", "16829", "16830", "16831", "16832", "16833", "16834", "16838", "16842", "16843", "16844", "16850", "16855", "16857", "16858", "16865", "16867", "16868", "16870", "16872", "16873", "16874", "16876", "16877", "16884", "16885", "16886", "16889", "16890", "16891", "16895", "16896", "16897", "16899", "16900", "16903", "16904", "16905", "16908", "16909", "16913", "16915", "16916", "16917", "16918", "16919", "16922", "16923", "16925", "16927", "16928", "16929", "16930", "16931", "16932", "16934", "16935", "16936", "16937", "16943", "16944", "16946", "16951", "16954", "16955", "16956", "16957", "16959", "16960", "16962", "16963", "16968", "16969", "16970", "16971", "16972", "16978", "16980", "16981", "16983", "16984", "16987", "16989", "16990", "16995", "16996", "16997", "16999", "17000", "17001", "17008", "17010", "17011", "17016", "17018", "17019", "17021", "17025", "17026", "17027", "17030", "17031", "17037", "17038", "17039", "17040", "17042", "17046", "17048", "17049", "17050", "17056", "17058", "17062", "17064", "17067", "17072", "17078", "17082", "17083", "17084", "17085", "17087", "17088", "17090", "17095", "17097", "17100", "17103", "17107", "17108", "17110", "17112", "17113", "17115", "17120", "17121", "17123", "17124", "17126", "17127", "17129", "17130", "17131", "17132", "17134", "17137", "17139", "17142", "17143", "17148", "17149", "17153", "17155", "17158", "17160", "17161", "17162", "17164", "17165", "17167", "17169", "17171", "17173", "17176", "17177", "17180", "17181", "17184", "17185", "17186", "17189", "17192", "17194", "17195", "17197", "17199", "17204", "17207", "17209", "17211", "17212", "17214", "17217", "17221", "17222", "17223", "17226", "17227", "17228", "17229", "17230", "17232", "17236", "17237", "17238", "17241", "17243", "17244", "17248", "17250", "17252", "17253", "17254", "17255", "17261", "17262", "17264", "17266", "17268", "17270", "17273", "17274", "17275", "17277", "17278", "17280", "17281", "17282", "17283", "17284", "17285", "17290", "17293", "17294", "17296", "17298", "17307", "17311", "17314", "17316", "17318", "17321", "17322", "17323", "17325", "17326", "17329", "17330", "17331", "17333", "17334", "17336", "17337", "17339", "17340", "17341", "17342", "17343", "17344", "17347", "17348", "17351", "17353", "17354", "17355", "17357", "17358", "17360", "17363", "17366", "17367", "17369", "17371", "17373", "17374", "17376", "17377", "17379", "17380", "17383", "17384", "17385", "17386", "17387", "17388", "17389", "17394", "17395", "17396", "17400", "17402", "17404", "17405", "17406", "17408", "17409", "17410", "17411", "17413", "17418", "17427", "17429", "17432", "17433", "17437", "17439", "17441", "17444", "17445", "17446", "17447", "17448", "17450", "17451", "17452", "17453", "17455", "17456", "17458", "17459", "17461", "17462", "17464", "17466", "17468", "17470", "17472", "17473", "17476", "17477", "17478", "17481", "17483", "17484", "17487", "17491", "17493", "17494", "17495", "17503", "17504", "17507", "17513", "17514", "17515", "17516", "17518", "17519", "17522", "17523", "17524", "17527", "17535", "17537", "17540", "17541", "17542", "17543", "17544", "17546", "17552", "17553", "17555", "17557", "17560", "17561", "17574", "17575", "17576", "17577", "17579", "17582", "17585", "17586", "17588", "17589", "17591", "17592", "17594", "17596", "17600", "17601", "17605", "17606", "17607", "17610", "17611", "17612", "17614", "17616", "17618", "17619", "17623", "17624", "17625", "17629", "17630", "17631", "17636", "17639", "17645", "17647", "17649", "17652", "17654", "17655", "17662", "17663", "17666", "17668", "17671", "17673", "17674", "17676", "17679", "17680", "17681", "17682", "17684", "17685", "17687", "17688", "17689", "17692", "17696", "17698", "17699", "17703", "17704", "17705", "17706", "17709", "17710", "17711", "17712", "17717", "17718", "17720", "17724", "17729", "17730", "17731", "17738", "17740", "17741", "17743", "17744", "17746", "17752", "17754", "17755", "17756", "17758", "17763", "17764", "17765", "17766", "17767", "17768", "17770", "17772", "17774", "17778", "17779", "17780", "17782", "17785", "17787", "17788", "17789", "17793", "17795", "17796", "17804", "17805", "17807", "17808", "17809", "17812", "17815", "17816", "17826", "17828", "17831", "17832", "17836", "17843", "17844", "17851", "17853", "17856", "17857", "17859", "17861", "17863", "17866", "17870", "17871", "17873", "17877", "17878", "17879", "17881", "17882", "17889", "17890", "17891", "17894", "17896", "17898", "17899", "17900", "17905", "17908", "17910", "17911", "17913", "17914", "17915", "17916", "17917", "17918", "17921", "17922", "17923", "17925", "17927", "17932", "17933", "17934", "17935", "17941", "17942", "17943", "17944", "17946", "17953", "17956", "17957", "17959", "17962", "17963", "17965", "17967", "17969", "17970", "17971", "17973", "17974", "17975", "17978", "17979", "17981", "17982", "17985", "17987", "17988", "17992", "17993", "17996", "17997", "18001", "18002", "18003", "18004", "18005", "18007", "18008", "18013", "18015", "18021", "18022", "18025", "18026", "18027", "18028", "18029", "18030", "18031", "18036", "18039", "18040", "18042", "18043", "18044", "18045", "18047", "18049", "18050", "18052", "18055", "18058", "18061", "18062", "18063", "18064", "18065", "18066", "18067", "18068", "18070", "18071", "18073", "18077", "18078", "18080", "18082", "18086", "18087", "18088", "18089", "18090", "18091", "18092", "18093", "18094", "18096", "18097", "18098", "18099", "18100", "18102", "18104", "18105", "18106", "18111", "18112", "18113", "18114", "18119", "18121", "18125", "18129", "18131", "18132", "18133", "18136", "18137", "18138", "18140", "18142", "18144", "18145", "18146", "18147", "18148", "18152", "18153", "18154", "18158", "18159", "18160", "18162", "18165", "18167", "18169", "18171", "18174", "18176", "18180", "18181", "18182", "18183", "18184", "18189", "18191", "18192", "18193", "18196", "18201", "18203", "18205", "18208", "18211", "18212", "18213", "18214", "18215", "18216", "18218", "18219", "18226", "18232", "18233", "18236", "18237", "18238", "18240", "18242", "18243", "18244", "18245", "18247", "18248", "18251", "18252", "18253", "18255", "18256", "18257", "18259", "18262", "18265", "18268", "18270", "18271", "18272", "18275", "18281", "18282", "18283", "18285", "18288", "18290", "18292", "18295", "18296", "18297", "18298", "18300", "18301", "18302", "18303", "18304", "18305", "18306", "18308", "18310", "18313", "18314", "18318", "18325", "18327", "18330", "18332", "18333", "18335", "18337", "18338", "18339", "18340", "18341", "18343", "18344", "18345", "18349", "18352", "18354", "18355", "18356", "18359", "18361", "18362", "18364", "18365", "18366", "18369", "18372", "18373", "18375", "18379", "18383", "18384", "18386", "18390", "18392", "18393", "18395", "18396", "18397", "18398", "18399", "18401", "18404", "18405", "18407", "18408", "18409", "18416", "18418", "18423", "18429", "18430", "18436", "18438", "18439", "18441", "18443", "18444", "18448", "18450", "18451", "18452", "18453", "18454", "18455", "18457", "18458", "18461", "18464", "18465", "18466", "18468", "18473", "18475", "18478", "18484", "18485", "18487", "18488", "18489", "18490", "18491", "18492", "18494", "18495", "18496", "18500", "18505", "18506", "18508", "18510", "18511", "18512", "18514", "18516", "18517", "18518", "18521", "18522", "18523", "18524", "18525", "18526", "18527", "18532", "18533", "18534", "18536", "18539", "18543", "18546", "18549", "18550", "18551", "18552", "18555", "18558", "18559", "18560", "18563", "18565", "18566", "18567", "18569", "18570", "18572", "18574", "18575", "18577", "18579", "18582", "18583", "18584", "18586", "18587", "18590", "18591", "18600", "18602", "18603", "18605", "18606", "18608", "18610", "18612", "18614", "18615", "18616", "18619", "18621", "18623", "18627", "18631", "18634", "18635", "18636", "18637", "18641", "18643", "18645", "18647", "18648", "18652", "18653", "18654", "18656", "18657", "18659", "18660", "18662", "18663", "18665", "18666", "18667", "18672", "18673", "18677", "18678", "18679", "18680", "18682", "18684", "18685", "18686", "18687", "18689", "18690", "18694", "18695", "18698", "18703", "18704", "18705", "18708", "18709", "18710", "18716", "18717", "18718", "18719", "18723", "18725", "18727", "18729", "18731", "18732", "18733", "18734", "18735", "18736", "18737", "18740", "18741", "18742", "18743", "18746", "18754", "18756", "18760", "18763", "18773", "18774", "18778", "18779", "18782", "18783", "18785", "18786", "18790", "18792", "18794", "18796", "18798", "18799", "18801", "18803", "18807", "18809", "18810", "18812", "18814", "18815", "18817", "18820", "18825", "18826", "18827", "18828", "18829", "18831", "18832", "18833", "18836", "18840", "18842", "18844", "18847", "18852", "18853", "18854", "18855", "18856", "18857", "18859", "18860", "18861", "18865", "18866", "18867", "18868", "18869", "18871", "18872", "18873", "18876", "18877", "18878", "18879", "18881", "18882", "18885", "18886", "18888", "18891", "18896", "18899", "18903", "18904", "18905", "18906", "18912", "18913", "18914", "18915", "18916", "18918", "18920", "18921", "18922", "18923", "18924", "18925", "18927", "18928", "18932", "18933", "18938", "18941", "18942", "18944", "18946", "18947", "18949", "18953", "18954", "18957", "18960", "18962", "18965", "18967", "18972", "18974", "18976", "18978", "18980", "18985", "18993", "18995", "18997", "18998", "19001", "19003", "19006", "19008", "19009", "19011", "19013", "19015", "19016", "19018", "19019", "19020", "19021", "19022", "19023", "19026", "19027", "19030", "19033", "19034", "19036", "19040", "19044", "19045", "19046", "19047", "19054", "19055", "19059", "19060", "19061", "19062", "19063", "19066", "19067", "19069", "19071", "19072", "19073", "19075", "19077", "19079", "19082", "19083", "19084", "19085", "19097", "19101", "19102", "19105", "19107", "19108", "19110", "19111", "19113", "19114", "19116", "19118", "19119", "19122", "19124", "19125", "19126", "19132", "19133", "19135", "19136", "19138", "19139", "19141", "19142", "19144", "19148", "19150", "19151", "19152", "19153", "19154", "19157", "19158", "19159", "19161", "19162", "19163", "19165", "19167", "19168", "19170", "19171", "19173", "19174", "19175", "19177", "19180", "19181", "19182", "19187", "19190", "19191", "19193", "19194", "19203", "19204", "19205", "19206", "19208", "19211", "19212", "19215", "19216", "19219", "19220", "19222", "19223", "19224", "19225", "19229", "19230", "19231", "19233", "19234", "19236", "19238", "19239", "19241", "19243", "19244", "19245", "19246", "19247", "19248", "19249", "19250", "19253", "19255", "19257", "19259", "19263", "19265", "19267", "19268", "19269", "19270", "19271", "19277", "19280", "19282", "19284", "19286", "19287", "19289", "19292", "19293", "19294", "19295", "19297", "19298", "19303", "19304", "19307", "19310", "19311", "19312", "19313", "19314", "19315", "19316", "19317", "19318", "19322", "19324", "19325", "19326", "19327", "19329", "19332", "19334", "19335", "19338", "19340", "19341", "19342", "19346", "19347", "19348", "19349", "19352", "19353", "19356", "19359", "19360", "19361", "19364", "19365", "19366", "19367", "19368", "19370", "19371", "19374", "19375", "19376", "19379", "19380", "19382", "19384", "19385", "19387", "19389", "19395", "19396", "19398", "19400", "19403", "19409", "19411", "19412", "19414", "19416", "19418", "19419", "19421", "19422", "19423", "19425", "19427", "19428", "19429", "19430", "19431", "19432", "19433", "19434", "19435", "19437", "19438", "19439", "19440", "19441", "19443", "19444", "19445", "19446", "19450", "19452", "19453", "19454", "19461", "19467", "19468", "19473", "19475", "19477", "19480", "19483", "19488", "19489", "19490", "19492", "19496", "19497", "19498", "19499", "19501", "19502", "19503", "19504", "19508", "19510", "19511", "19514", "19515", "19517", "19521", "19522", "19524", "19527", "19528", "19529", "19531", "19536", "19537", "19540", "19544", "19545", "19548", "19553", "19554", "19555", "19556", "19557", "19558", "19561", "19563", "19565", "19567", "19568", "19571", "19575", "19576", "19578", "19581", "19586", "19587", "19588", "19591", "19592", "19596", "19598", "19599", "19600", "19601", "19603", "19604", "19607", "19608", "19612", "19613", "19614", "19618", "19623", "19624", "19631", "19634", "19635", "19636", "19638", "19639", "19640", "19642", "19643", "19645", "19648", "19649", "19652", "19653", "19654", "19656", "19657", "19658", "19659", "19662", "19664", "19666", "19670", "19671", "19672", "19673", "19675", "19676", "19680", "19681", "19682", "19683", "19685", "19687", "19688", "19689", "19690", "19693", "19694", "19701", "19703", "19704", "19705", "19707", "19710", "19711", "19713", "19715", "19716", "19717", "19718", "19719", "19720", "19721", "19722", "19723", "19726", "19728", "19729", "19730", "19733", "19734", "19736", "19737", "19740", "19741", "19742", "19744", "19745", "19748", "19750", "19751", "19752", "19753", "19755", "19756", "19757", "19758", "19760", "19763", "19764", "19765", "19766", "19768", "19769", "19770", "19771", "19772", "19773", "19774", "19775", "19776", "19777", "19781", "19782", "19785", "19788", "19789", "19790", "19795", "19796", "19797", "19801", "19803", "19805", "19806", "19807", "19808", "19809", "19811", "19812", "19815", "19818", "19821", "19830", "19831", "19838", "19839", "19840", "19842", "19847", "19848", "19849", "19850", "19851", "19852", "19854", "19855", "19858", "19859", "19860", "19863", "19864", "19868", "19871", "19873", "19875", "19878", "19879", "19880", "19882", "19884", "19890", "19892", "19893", "19895", "19896", "19897", "19898", "19899", "19900", "19901", "19902", "19905", "19906", "19907", "19908", "19911", "19915", "19916", "19917", "19918", "19919", "19921", "19922", "19923", "19926", "19928", "19930", "19933", "19935", "19936", "19939", "19941", "19944", "19946", "19947", "19948", "19950", "19951", "19952", "19956", "19957", "19961", "19963", "19964", "19967", "19969", "19971", "19972", "19973", "19975", "19976", "19977", "19978", "19979", "19982", "19983", "19984", "19985", "19986", "19987", "19988", "19989", "19991", "19993", "19994", "19995", "19997", "19998", "19999", "20001", "20003", "20005", "20006", "20009", "20010", "20011", "20013", "20014", "20015", "20017", "20018", "20019", "20023", "20024", "20025", "20026", "20027", "20029", "20030", "20032", "20033", "20034", "20036", "20037", "20039", "20042", "20044", "20045", "20046", "20048", "20050", "20055", "20056", "20059", "20063", "20064", "20065", "20066", "20068", "20070", "20071", "20072", "20073", "20074", "20076", "20077", "20079", "20080", "20081", "20083", "20084", "20085", "20089", "20091", "20093", "20095", "20096", "20097", "20102", "20109", "20112", "20113", "20114", "20115", "20118", "20119", "20121", "20123", "20124", "20125", "20126", "20127", "20128", "20130", "20131", "20137", "20141", "20142", "20143", "20145", "20152", "20153", "20155", "20156", "20158", "20159", "20160", "20161", "20163", "20164", "20167", "20168", "20169", "20171", "20173", "20174", "20175", "20182", "20183", "20185", "20186", "20192", "20193", "20194", "20196", "20199", "20200", "20201", "20204", "20209", "20212", "20213", "20214", "20215", "20216", "20217", "20218", "20220", "20222", "20223", "20224", "20226", "20230", "20232", "20233", "20234", "20237", "20238", "20239", "20240", "20241", "20242", "20243", "20244", "20246", "20247", "20250", "20253", "20254", "20256", "20258", "20262", "20263", "20267", "20268", "20271", "20273", "20274", "20275", "20279", "20281", "20282", "20284", "20286", "20287", "20290", "20292", "20294", "20297", "20299", "20301", "20303", "20305", "20309", "20310", "20315", "20317", "20318", "20321", "20322", "20323", "20324", "20325", "20326", "20330", "20333", "20334", "20338", "20341", "20343", "20347", "20352", "20357", "20358", "20360", "20361", "20363", "20365", "20367", "20372", "20380", "20381", "20382", "20383", "20385", "20389", "20394", "20396", "20397", "20399", "20405", "20407", "20409", "20410", "20412", "20416", "20417", "20418", "20421", "20424", "20428", "20429", "20431", "20434", "20436", "20437", "20438", "20439", "20441", "20442", "20444", "20446", "20447", "20448", "20451", "20452", "20453", "20456", "20457", "20460", "20462", "20465", "20466", "20469", "20471", "20472", "20473", "20475", "20476", "20479", "20480", "20482", "20491", "20493", "20494", "20495", "20496", "20497", "20499", "20500", "20501", "20503", "20507", "20508", "20509", "20510", "20511", "20512", "20514", "20515", "20517", "20519", "20527", "20528", "20532", "20533", "20535", "20536", "20538", "20540", "20545", "20546", "20547", "20548", "20549", "20551", "20552", "20554", "20556", "20558", "20565", "20567", "20570", "20571", "20572", "20574", "20575", "20576", "20577", "20582", "20586", "20587", "20588", "20590", "20592", "20593", "20594", "20599", "20603", "20605", "20606", "20608", "20609", "20611", "20616", "20617", "20619", "20621", "20622", "20623", "20625", "20630", "20632", "20634", "20637", "20638", "20639", "20641", "20643", "20646", "20647", "20648", "20650", "20651", "20652", "20653", "20655", "20658", "20661", "20665", "20667", "20669", "20670", "20674", "20676", "20677", "20678", "20680", "20681", "20682", "20687", "20692", "20693", "20697", "20698", "20699", "20700", "20701", "20703", "20705", "20707", "20708", "20709", "20711", "20716", "20717", "20718", "20720", "20722", "20723", "20724", "20733", "20734", "20736", "20737", "20743", "20744", "20745", "20746", "20750", "20752", "20753", "20755", "20756", "20757", "20758", "20759", "20761", "20764", "20765", "20766", "20767", "20770", "20772", "20773", "20774", "20775", "20776", "20778", "20779", "20780", "20781", "20783", "20784", "20785", "20789", "20791", "20792", "20793", "20794", "20797", "20798", "20800", "20802", "20804", "20807", "20808", "20809", "20810", "20812", "20816", "20818", "20819", "20820", "20823", "20825", "20826", "20827", "20828", "20829", "20832", "20833", "20834", "20835", "20836", "20837", "20840", "20841", "20842", "20843", "20844", "20848", "20850", "20853", "20854", "20861", "20862", "20865", "20866", "20869", "20871", "20872", "20875", "20876", "20877", "20880", "20881", "20882", "20883", "20884", "20885", "20886", "20887", "20891", "20895", "20896", "20901", "20903", "20904", "20905", "20906", "20908", "20909", "20910", "20911", "20912", "20914", "20915", "20916", "20918", "20920", "20921", "20923", "20924", "20926", "20928", "20929", "20930", "20931", "20934", "20936", "20937", "20938", "20939", "20941", "20947", "20950", "20952", "20953", "20955", "20956", "20958", "20962", "20963", "20964", "20966", "20968", "20970", "20971", "20979", "20982", "20985", "20986", "20987", "20988", "20990", "20991", "20993", "20995", "20997", "21000", "21001", "21010", "21011", "21012", "21013", "21014", "21016", "21019", "21020", "21025", "21031", "21033", "21035", "21036", "21037", "21041", "21044", "21045", "21046", "21047", "21050", "21051", "21052", "21054", "21055", "21061", "21062", "21063", "21065", "21066", "21067", "21070", "21074", "21076", "21079", "21080", "21081", "21082", "21083", "21085", "21087", "21090", "21091", "21092", "21093", "21094", "21096", "21097", "21099", "21102", "21103", "21105", "21107", "21108", "21109", "21112", "21115", "21117", "21118", "21119", "21120", "21124", "21125", "21126", "21127", "21129", "21131", "21132", "21134", "21135", "21138", "21143", "21145", "21147", "21152", "21153", "21154", "21155", "21156", "21158", "21159", "21162", "21163", "21164", "21165", "21172", "21174", "21176", "21177", "21180", "21182", "21183", "21185", "21186", "21191", "21192", "21196", "21197", "21199", "21201", "21203", "21209", "21210", "21213", "21214", "21215", "21219", "21220", "21222", "21225", "21226", "21228", "21229", "21230", "21233", "21235", "21237", "21238", "21239", "21242", "21243", "21247", "21249", "21251", "21252", "21259", "21261", "21262", "21263", "21265", "21266", "21267", "21271", "21272", "21273", "21275", "21276", "21277", "21278", "21282", "21285", "21286", "21287", "21288", "21289", "21290", "21291", "21292", "21293", "21294", "21295", "21296", "21298", "21300", "21302", "21303", "21306", "21307", "21317", "21318", "21319", "21320", "21322", "21323", "21328", "21332", "21333", "21334", "21335", "21340", "21341", "21344", "21346", "21348", "21349", "21355", "21356", "21357", "21362", "21365", "21366", "21367", "21369", "21370", "21372", "21375", "21377", "21378", "21379", "21380", "21381", "21384", "21389", "21390", "21392", "21393", "21395", "21396", "21400", "21402", "21403", "21405", "21407", "21408", "21409", "21411", "21412", "21415", "21416", "21417", "21418", "21419", "21420", "21421", "21422", "21424", "21426", "21428", "21429", "21430", "21432", "21433", "21434", "21437", "21438", "21439", "21440", "21442", "21447", "21449", "21450", "21452", "21453", "21455", "21457", "21459", "21460", "21464", "21466", "21470", "21471", "21472", "21474", "21478", "21481", "21482", "21484", "21485", "21490", "21491", "21492", "21494", "21495", "21497", "21498", "21499", "21500", "21501", "21502", "21505", "21506", "21507", "21508", "21510", "21511", "21512", "21514", "21515", "21516", "21517", "21522", "21523", "21524", "21527", "21529", "21532", "21534", "21537", "21538", "21539", "21541", "21543", "21545", "21547", "21548", "21551", "21552", "21555", "21557", "21558", "21559", "21560", "21562", "21568", "21569", "21573", "21574", "21581", "21584", "21585", "21586", "21587", "21588", "21589", "21591", "21595", "21596", "21599", "21600", "21601", "21602", "21603", "21605", "21608", "21609", "21610", "21614", "21615", "21617", "21620", "21624", "21625", "21627", "21628", "21635", "21644", "21645", "21647", "21648", "21653", "21654", "21655", "21660", "21661", "21662", "21665", "21666", "21667", "21669", "21670", "21671", "21672", "21674", "21675", "21676", "21677", "21678", "21679", "21680", "21681", "21684", "21688", "21690", "21691", "21692", "21698", "21705", "21707", "21708", "21712", "21713", "21714", "21716", "21717", "21721", "21724", "21725", "21726", "21731", "21737", "21738", "21739", "21741", "21743", "21744", "21746", "21748", "21749", "21754", "21755", "21756", "21757", "21761", "21762", "21763", "21767", "21768", "21769", "21770", "21772", "21775", "21776", "21777", "21779", "21780", "21784", "21785", "21786", "21787", "21789", "21790", "21791", "21792", "21793", "21795", "21796", "21797", "21798", "21801", "21804", "21806", "21808", "21809", "21812", "21816", "21817", "21818", "21819", "21821", "21823", "21824", "21825", "21826", "21827", "21830", "21831", "21833", "21837", "21839", "21841", "21843", "21845", "21846", "21853", "21855", "21856", "21858", "21861", "21863", "21867", "21871", "21872", "21874", "21875", "21878", "21881", "21882", "21886", "21889", "21890", "21891", "21894", "21896", "21897", "21900", "21901", "21903", "21904", "21906", "21907", "21910", "21912", "21917", "21918", "21923", "21924", "21925", "21929", "21930", "21931", "21932", "21935", "21936", "21937", "21940", "21943", "21945", "21946", "21950", "21955", "21957", "21959", "21960", "21961", "21962", "21965", "21966", "21967", "21968", "21970", "21971", "21973", "21974", "21975", "21976", "21980", "21981", "21982", "21983", "21984", "21988", "21989", "21990", "21992", "21993", "21994", "21995", "21998", "22002", "22003", "22004", "22005", "22007", "22008", "22011", "22012", "22015", "22016", "22019", "22021", "22022", "22025", "22027", "22031", "22032", "22034", "22035", "22039", "22040", "22043", "22045", "22047", "22049", "22051", "22053", "22055", "22056", "22057", "22059", "22061", "22064", "22065", "22066", "22068", "22069", "22072", "22076", "22079", "22082", "22083", "22084", "22085", "22088", "22089", "22092", "22094", "22095", "22096", "22097", "22099", "22104", "22108", "22109", "22110", "22114", "22115", "22118", "22120", "22126", "22127", "22128", "22129", "22131", "22133", "22135", "22136", "22137", "22139", "22146", "22148", "22150", "22152", "22154", "22155", "22156", "22157", "22159", "22162", "22165", "22167", "22168", "22171", "22173", "22176", "22177", "22181", "22182", "22185", "22188", "22189", "22190", "22191", "22193", "22194", "22195", "22198", "22204", "22207", "22208", "22210", "22211", "22212", "22214", "22216", "22221", "22227", "22228", "22231", "22232", "22237", "22242", "22244", "22246", "22250", "22252", "22253", "22254", "22257", "22259", "22260", "22262", "22263", "22264", "22265", "22267", "22269", "22270", "22272", "22274", "22275", "22276", "22277", "22278", "22279", "22280", "22282", "22283", "22285", "22291", "22292", "22293", "22296", "22298", "22301", "22302", "22306", "22308", "22309", "22311", "22312", "22314", "22315", "22316", "22317", "22319", "22321", "22322", "22325", "22327", "22328", "22330", "22335", "22337", "22339", "22341", "22343", "22344", "22346", "22347", "22351", "22353", "22361", "22363", "22364", "22365", "22367", "22368", "22369", "22374", "22375", "22376", "22378", "22379", "22382", "22383", "22386", "22387", "22390", "22391", "22393", "22394", "22395", "22404", "22405", "22407", "22413", "22415", "22417", "22418", "22419", "22424", "22426", "22434", "22435", "22436", "22439", "22440", "22441", "22442", "22443", "22444", "22445", "22449", "22451", "22452", "22453", "22456", "22458", "22459", "22460", "22462", "22463", "22465", "22466", "22467", "22469", "22470", "22472", "22474", "22475", "22479", "22480", "22482", "22484", "22485", "22486", "22488", "22489", "22491", "22492", "22495", "22499", "22500", "22501", "22502", "22503", "22505", "22506", "22509", "22511", "22514", "22517", "22518", "22519", "22523", "22525", "22526", "22528", "22529", "22531", "22536", "22537", "22538", "22541", "22544", "22546", "22550", "22551", "22555", "22558", "22560", "22561", "22565", "22568", "22569", "22570", "22572", "22573", "22574", "22577", "22579", "22581", "22582", "22585", "22587", "22588", "22589", "22591", "22593", "22594", "22595", "22597", "22598", "22599", "22602", "22603", "22604", "22608", "22609", "22611", "22612", "22614", "22615", "22617", "22624", "22625", "22627", "22628", "22629", "22631", "22632", "22633", "22638", "22639", "22641", "22644", "22647", "22650", "22651", "22653", "22654", "22655", "22656", "22660", "22662", "22663", "22665", "22666", "22667", "22668", "22669", "22670", "22672", "22673", "22677", "22679", "22680", "22681", "22682", "22686", "22687", "22688", "22689", "22690", "22693", "22694", "22696", "22697", "22699", "22701", "22704", "22706", "22707", "22709", "22714", "22717", "22720", "22726", "22728", "22729", "22731", "22733", "22742", "22745", "22747", "22748", "22751", "22752", "22758", "22759", "22764", "22765", "22766", "22771", "22773", "22774", "22775", "22777", "22780", "22782", "22783", "22787", "22789", "22790", "22792", "22800", "22802", "22803", "22805", "22809", "22810", "22815", "22818", "22820", "22821", "22824", "22825", "22826", "22827", "22828", "22830", "22831", "22832", "22833", "22835", "22838", "22840", "22842", "22843", "22844", "22847", "22848", "22854", "22855", "22856", "22857", "22858", "22863", "22867", "22869", "22872", "22873", "22874", "22875", "22876", "22877", "22878", "22879", "22880", "22886", "22887", "22888", "22890", "22891", "22892", "22896", "22897", "22898", "22900", "22908", "22909", "22910", "22911", "22913", "22915", "22917", "22918", "22919", "22924", "22925", "22926", "22928", "22930", "22931", "22932", "22933", "22939", "22941", "22942", "22943", "22945", "22947", "22949", "22952", "22953", "22954", "22957", "22958", "22960", "22962", "22964", "22967", "22968", "22969", "22973", "22975", "22976", "22980", "22983", "22984", "22987", "22989", "22990", "22992", "22993", "22994", "22997", "22998", "22999", "23001", "23005", "23006", "23007", "23011", "23015", "23017", "23018", "23026", "23029", "23037", "23038", "23039", "23042", "23044", "23045", "23047", "23048", "23052", "23053", "23054", "23057", "23058", "23059", "23062", "23064", "23065", "23070", "23072", "23074", "23075", "23078", "23079", "23080", "23082", "23088", "23089", "23092", "23094", "23095", "23098", "23100", "23101", "23102", "23103", "23105", "23106", "23107", "23108", "23110", "23111", "23113", "23117", "23120", "23122", "23127", "23131", "23132", "23134", "23141", "23142", "23146", "23147", "23149", "23150", "23151", "23154", "23155", "23157", "23164", "23165", "23166", "23167", "23168", "23169", "23171", "23172", "23173", "23174", "23179", "23181", "23183", "23185", "23186", "23188", "23192", "23193", "23194", "23195", "23196", "23197", "23198", "23200", "23201", "23202", "23203", "23204", "23207", "23208", "23210", "23211", "23216", "23217", "23218", "23220", "23226", "23227", "23228", "23231", "23232", "23233", "23237", "23239", "23242", "23244", "23247", "23249", "23251", "23252", "23253", "23255", "23257", "23261", "23264", "23266", "23267", "23268", "23269", "23272", "23273", "23274", "23279", "23280", "23283", "23284", "23291", "23295", "23296", "23299", "23300", "23301", "23306", "23308", "23311", "23316", "23317", "23318", "23319", "23320", "23321", "23322", "23323", "23324", "23326", "23327", "23329", "23330", "23332", "23333", "23336", "23340", "23343", "23344", "23345", "23347", "23348", "23350", "23351", "23352", "23354", "23355", "23358", "23359", "23362", "23363", "23369", "23371", "23372", "23373", "23374", "23375", "23382", "23383", "23384", "23385", "23387", "23389", "23391", "23393", "23394", "23396", "23397", "23400", "23403", "23405", "23408", "23409", "23410", "23411", "23412", "23413", "23417", "23418", "23419", "23424", "23426", "23428", "23431", "23432", "23435", "23438", "23439", "23440", "23441", "23443", "23446", "23447", "23449", "23450", "23452", "23453", "23455", "23457", "23458", "23461", "23463", "23465", "23466", "23468", "23470", "23471", "23474", "23475", "23476", "23477", "23478", "23479", "23480", "23481", "23487", "23489", "23490", "23493", "23499", "23500", "23503", "23505", "23506", "23510", "23511", "23512", "23514", "23515", "23516", "23518", "23519", "23521", "23523", "23526", "23527", "23529", "23531", "23532", "23534", "23536", "23540", "23542", "23544", "23551", "23553", "23555", "23557", "23562", "23568", "23569", "23573", "23574", "23575", "23576", "23578", "23581", "23586", "23587", "23588", "23590", "23597", "23598", "23599", "23600", "23601", "23602", "23604", "23606", "23608", "23611", "23613", "23620", "23622", "23624", "23625", "23632", "23634", "23638", "23644", "23647", "23649", "23651", "23656", "23659", "23660", "23664", "23667", "23668", "23669", "23671", "23672", "23675", "23676", "23684", "23685", "23687", "23690", "23691", "23692", "23694", "23695", "23698", "23701", "23702", "23703", "23706", "23707", "23708", "23711", "23712", "23714", "23715", "23716", "23719", "23722", "23723", "23724", "23725", "23726", "23727", "23728", "23730", "23731", "23732", "23734", "23735", "23736", "23737", "23741", "23748", "23750", "23751", "23752", "23753", "23756", "23757", "23760", "23762", "23763", "23764", "23766", "23767", "23768", "23769", "23775", "23776", "23778", "23780", "23781", "23783", "23785", "23787", "23788", "23789", "23791", "23792", "23795", "23796", "23797", "23798", "23800", "23802", "23803", "23804", "23806", "23807", "23810", "23811", "23814", "23816", "23822", "23823", "23824", "23826", "23827", "23829", "23831", "23832", "23835", "23839", "23840", "23841", "23843", "23844", "23845", "23847", "23849", "23850", "23851", "23852", "23853", "23854", "23857", "23860", "23865", "23866", "23868", "23869", "23871", "23872", "23874", "23875", "23876", "23877", "23879", "23880", "23882", "23886", "23888", "23889", "23890", "23891", "23892", "23894", "23896", "23900", "23901", "23902", "23903", "23904", "23912", "23915", "23916", "23917", "23918", "23919", "23920", "23921", "23923", "23924", "23926", "23929", "23930", "23931", "23933", "23936", "23937", "23938", "23939", "23940", "23943", "23947", "23948", "23951", "23953", "23955", "23956", "23957", "23958", "23960", "23962", "23965", "23969", "23970", "23971", "23972", "23974", "23975", "23977", "23979", "23980", "23981", "23982", "23986", "23991", "23992", "23995", "24000", "24003", "24004", "24006", "24011", "24016", "24021", "24022", "24024", "24026", "24027", "24028", "24030", "24032", "24035", "24037", "24038", "24044", "24046", "24049", "24050", "24051", "24053", "24054", "24055", "24059", "24060", "24061", "24063", "24064", "24067", "24069", "24072", "24075", "24077", "24078", "24079", "24082", "24084", "24086", "24087", "24091", "24099", "24100", "24101", "24102", "24104", "24105", "24106", "24107", "24108", "24110", "24111", "24112", "24113", "24114", "24116", "24117", "24118", "24119", "24121", "24122", "24125", "24127", "24128", "24132", "24134", "24135", "24137", "24139", "24145", "24147", "24148", "24150", "24152", "24153", "24154", "24156", "24158", "24159", "24160", "24164", "24166", "24171", "24172", "24173", "24174", "24176", "24178", "24179", "24180", "24182", "24183", "24185", "24188", "24190", "24191", "24192", "24193", "24196", "24198", "24199", "24204", "24205", "24206", "24208", "24211", "24214", "24216", "24219", "24221", "24230", "24231", "24234", "24235", "24240", "24242", "24243", "24246", "24248", "24249", "24252", "24254", "24255", "24256", "24258", "24260", "24264", "24267", "24268", "24270", "24271", "24275", "24276", "24277", "24278", "24281", "24282", "24283", "24286", "24287", "24288", "24289", "24290", "24291", "24293", "24295", "24298", "24300", "24301", "24305", "24306", "24307", "24309", "24310", "24312", "24313", "24314", "24318", "24320", "24321", "24322", "24327", "24330", "24331", "24333", "24334", "24335", "24341", "24342", "24343", "24344", "24345", "24346", "24349", "24350", "24352", "24353", "24354", "24355", "24357", "24362", "24363", "24365", "24366", "24367", "24368", "24369", "24371", "24372", "24373", "24374", "24375", "24376", "24377", "24378", "24380", "24383", "24386", "24387", "24390", "24391", "24392", "24398", "24400", "24401", "24402", "24404", "24407", "24408", "24409", "24411", "24413", "24416", "24417", "24418", "24422", "24425", "24428", "24430", "24432", "24433", "24434", "24436", "24437", "24438", "24441", "24443", "24446", "24447", "24448", "24449", "24451", "24453", "24456", "24460", "24462", "24463", "24464", "24465", "24466", "24468", "24469", "24470", "24473", "24477", "24478", "24480", "24483", "24485", "24486", "24488", "24489", "24490", "24491", "24492", "24493", "24495", "24496", "24499", "24500", "24501", "24502", "24506", "24510", "24513", "24514", "24515", "24516", "24517", "24519", "24528", "24529", "24531", "24533", "24534", "24535", "24537", "24546", "24552", "24553", "24554", "24555", "24558", "24561", "24562", "24569", "24571", "24572", "24574", "24575", "24576", "24582", "24583", "24585", "24587", "24589", "24591", "24592", "24593", "24594", "24596", "24597", "24599", "24601", "24605", "24606", "24608", "24611", "24613", "24614", "24615", "24616", "24617", "24618", "24619", "24622", "24626", "24628", "24631", "24635", "24637", "24638", "24640", "24643", "24645", "24648", "24650", "24651", "24652", "24653", "24654", "24655", "24658", "24659", "24661", "24662", "24665", "24666", "24668", "24669", "24670", "24674", "24681", "24683", "24687", "24689", "24691", "24692", "24693", "24695", "24697", "24701", "24704", "24705", "24710", "24711", "24713", "24714", "24715", "24718", "24722", "24725", "24727", "24728", "24730", "24732", "24736", "24739", "24740", "24741", "24744", "24745", "24746", "24747", "24748", "24749", "24750", "24751", "24753", "24756", "24762", "24763", "24764", "24766", "24768", "24769", "24770", "24778", "24779", "24780", "24781", "24783", "24784", "24785", "24787", "24799", "24805", "24806", "24808", "24809", "24810", "24812", "24814", "24817", "24819", "24820", "24821", "24824", "24827", "24828", "24829", "24830", "24832", "24835", "24838", "24840", "24843", "24844", "24847", "24850", "24851", "24853", "24854", "24855", "24856", "24860", "24862", "24863", "24865", "24866", "24867", "24870", "24871", "24872", "24874", "24875", "24878", "24879", "24880", "24882", "24885", "24886", "24888", "24889", "24890", "24891", "24892", "24895", "24896", "24897", "24898", "24899", "24900", "24901", "24903", "24904", "24905", "24906", "24907", "24909", "24911", "24912", "24917", "24918", "24919", "24920", "24923", "24924", "24930", "24932", "24933", "24934", "24938", "24939", "24941", "24942", "24943", "24944", "24946", "24948", "24950", "24953", "24955", "24956", "24957", "24960", "24961", "24962", "24965", "24969", "24970", "24971", "24974", "24975", "24976", "24979", "24980", "24982", "24983", "24984", "24986", "24987", "24989", "24990", "24991", "24999", "25004", "25005", "25008", "25010", "25012", "25016", "25017", "25024", "25027", "25028", "25031", "25033", "25034", "25037", "25040", "25042", "25044", "25046", "25047", "25048", "25054", "25055", "25057", "25058", "25059", "25066", "25067", "25069", "25070", "25071", "25078", "25079", "25080", "25081", "25082", "25086", "25089", "25090", "25093", "25094", "25096", "25102", "25104", "25105", "25108", "25111", "25112", "25113", "25114", "25116", "25118", "25121", "25122", "25124", "25126", "25128", "25129", "25130", "25131", "25133", "25138", "25139", "25142", "25143", "25144", "25148", "25151", "25152", "25153", "25154", "25158", "25159", "25160", "25162", "25163", "25164", "25166", "25168", "25170", "25171", "25172", "25173", "25176", "25178", "25179", "25181", "25183", "25187", "25188", "25190", "25194", "25195", "25197", "25198", "25199", "25201", "25203", "25205", "25207", "25208", "25209", "25210", "25211", "25212", "25216", "25223", "25224", "25227", "25231", "25237", "25239", "25240", "25241", "25242", "25243", "25244", "25248", "25249", "25256", "25258", "25259", "25262", "25265", "25268", "25270", "25274", "25276", "25277", "25278", "25282", "25284", "25288", "25290", "25292", "25293", "25299", "25302", "25303", "25305", "25306", "25307", "25310", "25317", "25318", "25319", "25323", "25332", "25337", "25338", "25339", "25340", "25342", "25354", "25358", "25359", "25360", "25364", "25365", "25367", "25368", "25369", "25370", "25371", "25376", "25377", "25378", "25380", "25382", "25386", "25387", "25388", "25389", "25390", "25391", "25393", "25396", "25401", "25402", "25403", "25411", "25413", "25415", "25417", "25419", "25421", "25422", "25423", "25424", "25425", "25428", "25429", "25432", "25433", "25435", "25437", "25438", "25439", "25444", "25448", "25451", "25452", "25456", "25457", "25460", "25463", "25466", "25469", "25470", "25478", "25481", "25482", "25483", "25484", "25485", "25487", "25488", "25489", "25498", "25500", "25501", "25502", "25504", "25505", "25506", "25508", "25509", "25510", "25511", "25516", "25517", "25518", "25519", "25521", "25523", "25525", "25526", "25527", "25528", "25531", "25532", "25533", "25535", "25536", "25537", "25538", "25540", "25541", "25542", "25543", "25547", "25549", "25550", "25551", "25552", "25553", "25558", "25559", "25560", "25561", "25562", "25565", "25573", "25577", "25578", "25580", "25581", "25583", "25587", "25588", "25589", "25590", "25591", "25592", "25595", "25596", "25598", "25600", "25603", "25607", "25609", "25610", "25612", "25615", "25616", "25617", "25626", "25628", "25633", "25634", "25636", "25637", "25639", "25640", "25641", "25645", "25646", "25647", "25648", "25649", "25650", "25651", "25653", "25654", "25655", "25658", "25660", "25662", "25666", "25667", "25669", "25671", "25673", "25674", "25675", "25676", "25679", "25682", "25683", "25685", "25686", "25689", "25690", "25692", "25695", "25698", "25699", "25700", "25701", "25703", "25706", "25708", "25709", "25710", "25711", "25713", "25716", "25718", "25720", "25721", "25724", "25725", "25727", "25730", "25732", "25734", "25736", "25738", "25739", "25746", "25748", "25749", "25752", "25754", "25760", "25762", "25763", "25765", "25766", "25767", "25768", "25774", "25778", "25780", "25781", "25782", "25784", "25785", "25787", "25788", "25791", "25792", "25793", "25795", "25796", "25797", "25800", "25802", "25803", "25805", "25806", "25808", "25810", "25812", "25813", "25814", "25815", "25820", "25821", "25822", "25825", "25833", "25837", "25839", "25840", "25841", "25843", "25854", "25856", "25860", "25862", "25865", "25866", "25867", "25868", "25871", "25873", "25875", "25878", "25881", "25883", "25884", "25886", "25887", "25891", "25892", "25893", "25900", "25901", "25902", "25908", "25909", "25912", "25913", "25914", "25915", "25918", "25919", "25920", "25921", "25922", "25925", "25927", "25933", "25934", "25935", "25936", "25937", "25940", "25950", "25951", "25953", "25956", "25959", "25960", "25962", "25964", "25965", "25966", "25968", "25969", "25971", "25972", "25973", "25976", "25979", "25981", "25985", "25988", "25990", "25991", "25993", "25994", "25995", "25997", "26000", "26003", "26007", "26013", "26014", "26019", "26021", "26023", "26024", "26027", "26028", "26029", "26030", "26032", "26034", "26037", "26038", "26039", "26040", "26043", "26045", "26052", "26058", "26059", "26064", "26065", "26067", "26068", "26069", "26070", "26071", "26074", "26075", "26076", "26077", "26079", "26080", "26082", "26083", "26084", "26085", "26086", "26087", "26089", "26090", "26091", "26092", "26094", "26100", "26101", "26102", "26105", "26107", "26109", "26111", "26115", "26117", "26120", "26121", "26122", "26123", "26126", "26127", "26136", "26142", "26143", "26146", "26148", "26150", "26151", "26152", "26155", "26157", "26160", "26162", "26164", "26165", "26168", "26169", "26170", "26172", "26173", "26174", "26177", "26181", "26183", "26186", "26191", "26192", "26194", "26196", "26197", "26201", "26202", "26204", "26205", "26206", "26207", "26208", "26209", "26211", "26212", "26216", "26217", "26218", "26219", "26221", "26223", "26224", "26225", "26227", "26230", "26232", "26235", "26236", "26241", "26242", "26243", "26244", "26245", "26246", "26247", "26253", "26255", "26256", "26257", "26258", "26259", "26260", "26261", "26262", "26263", "26264", "26266", "26271", "26272", "26274", "26275", "26278", "26279", "26280", "26284", "26285", "26288", "26291", "26295", "26296", "26297", "26298", "26299", "26302", "26303", "26304", "26306", "26307", "26312", "26313", "26315", "26316", "26319", "26320", "26322", "26326", "26331", "26332", "26333", "26335", "26336", "26339", "26340", "26341", "26342", "26344", "26345", "26346", "26348", "26352", "26353", "26355", "26357", "26359", "26360", "26365", "26366", "26367", "26369", "26371", "26375", "26376", "26378", "26380", "26381", "26382", "26383", "26384", "26385", "26387", "26388", "26389", "26390", "26391", "26397", "26400", "26402", "26404", "26410", "26411", "26414", "26420", "26421", "26422", "26423", "26425", "26428", "26436", "26438", "26439", "26445", "26446", "26448", "26449", "26454", "26455", "26457", "26459", "26461", "26465", "26466", "26467", "26468", "26469", "26471", "26474", "26478", "26481", "26482", "26485", "26486", "26490", "26491", "26492", "26493", "26494", "26496", "26501", "26507", "26511", "26513", "26517", "26518", "26519", "26527", "26528", "26529", "26532", "26534", "26535", "26536", "26539", "26542", "26544", "26545", "26547", "26548", "26551", "26553", "26554", "26555", "26556", "26557", "26558", "26559", "26562", "26563", "26566", "26568", "26570", "26572", "26574", "26575", "26579", "26581", "26583", "26584", "26585", "26586", "26587", "26588", "26589", "26592", "26598", "26601", "26602", "26603", "26606", "26611", "26615", "26616", "26619", "26622", "26624", "26627", "26629", "26630", "26631", "26632", "26636", "26637", "26638", "26641", "26643", "26647", "26648", "26650", "26651", "26652", "26655", "26656", "26658", "26660", "26663", "26665", "26666", "26667", "26669", "26671", "26674", "26675", "26679", "26680", "26683", "26689", "26691", "26692", "26693", "26694", "26695", "26696", "26697", "26699", "26700", "26704", "26706", "26710", "26711", "26713", "26714", "26715", "26716", "26717", "26721", "26722", "26725", "26727", "26728", "26730", "26731", "26734", "26735", "26736", "26738", "26740", "26741", "26743", "26746", "26749", "26750", "26752", "26754", "26758", "26759", "26760", "26761", "26762", "26763", "26764", "26765", "26767", "26768", "26770", "26771", "26772", "26773", "26774", "26776", "26778", "26779", "26781", "26782", "26783", "26784", "26785", "26788", "26789", "26790", "26791", "26792", "26793", "26795", "26801", "26802", "26804", "26805", "26807", "26810", "26813", "26814", "26815", "26816", "26817", "26818", "26819", "26820", "26823", "26825", "26827", "26828", "26829", "26833", "26834", "26836", "26837", "26838", "26842", "26845", "26847", "26848", "26849", "26850", "26851", "26852", "26853", "26854", "26855", "26857", "26860", "26862", "26863", "26864", "26865", "26869", "26870", "26872", "26873", "26876", "26877", "26878", "26881", "26882", "26885", "26886", "26887", "26889", "26891", "26892", "26894", "26895", "26897", "26900", "26902", "26914", "26915", "26918", "26919", "26925", "26926", "26927", "26929", "26930", "26933", "26934", "26937", "26945", "26946", "26947", "26948", "26949", "26950", "26951", "26952", "26954", "26955", "26957", "26958", "26959", "26961", "26963", "26964", "26968", "26970", "26971", "26972", "26976", "26977", "26978", "26980", "26981", "26982", "26983", "26984", "26985", "26989", "26990", "26991", "26992", "26993", "26994", "26996", "26999", "27000", "27001", "27002", "27003", "27004", "27005", "27008", "27009", "27013", "27014", "27016", "27017", "27018", "27019", "27023", "27024", "27025", "27028", "27029", "27032", "27035", "27036", "27037", "27038", "27039", "27040", "27042", "27047", "27048", "27049", "27050", "27051", "27052", "27054", "27055", "27056", "27057", "27058", "27063", "27064", "27065", "27066", "27068", "27069", "27071", "27074", "27077", "27079", "27080", "27082", "27084", "27085", "27087", "27088", "27089", "27090", "27092", "27094", "27097", "27098", "27100", "27101", "27102", "27103", "27108", "27111", "27112", "27113", "27115", "27117", "27118", "27120", "27122", "27124", "27125", "27126", "27128", "27132", "27133", "27134", "27139", "27141", "27146", "27147", "27150", "27152", "27154", "27156", "27158", "27159", "27163", "27164", "27165", "27168", "27171", "27172", "27173", "27176", "27181", "27187", "27188", "27190", "27191", "27192", "27194", "27195", "27196", "27197", "27198", "27199", "27202", "27204", "27206", "27207", "27208", "27209", "27210", "27213", "27215", "27217", "27218", "27221", "27222", "27223", "27226", "27230", "27231", "27233", "27236", "27237", "27239", "27240", "27241", "27242", "27243", "27245", "27246", "27247", "27249", "27250", "27253", "27254", "27257", "27258", "27259", "27263", "27265", "27269", "27270", "27274", "27275", "27278", "27279", "27281", "27282", "27289", "27290", "27292", "27293", "27294", "27296", "27298", "27299", "27302", "27303", "27304", "27306", "27308", "27310", "27314", "27315", "27317", "27319", "27321", "27323", "27325", "27330", "27335", "27340", "27342", "27343", "27344", "27345", "27347", "27349", "27350", "27351", "27357", "27358", "27360", "27362", "27369", "27371", "27375", "27376", "27377", "27378", "27380", "27381", "27382", "27386", "27387", "27389", "27390", "27391", "27395", "27396", "27397", "27398", "27400", "27402", "27405", "27409", "27410", "27411", "27416", "27419", "27421", "27425", "27426", "27427", "27428", "27429", "27430", "27431", "27432", "27434", "27436", "27440", "27443", "27444", "27445", "27447", "27452", "27453", "27454", "27457", "27459", "27460", "27461", "27463", "27470", "27472", "27473", "27474", "27476", "27478", "27481", "27482", "27483", "27486", "27487", "27488", "27489", "27491", "27492", "27495", "27496", "27497", "27501", "27502", "27503", "27506", "27507", "27508", "27510", "27511", "27512", "27514", "27515", "27517", "27518", "27519", "27520", "27521", "27526", "27528", "27529", "27530", "27534", "27536", "27537", "27539", "27540", "27542", "27543", "27544", "27545", "27547", "27549", "27551", "27553", "27554", "27556", "27557", "27560", "27561", "27562", "27563", "27565", "27566", "27568", "27569", "27570", "27571", "27572", "27574", "27575", "27576", "27578", "27579", "27581", "27584", "27588", "27590", "27593", "27596", "27597", "27598", "27600", "27601", "27602", "27605", "27607", "27608", "27609", "27615", "27618", "27619", "27623", "27624", "27626", "27627", "27628", "27630", "27634", "27635", "27636", "27637", "27640", "27643", "27644", "27646", "27648", "27650", "27651", "27652", "27653", "27657", "27659", "27661", "27663", "27664", "27666", "27667", "27670", "27671", "27674", "27676", "27678", "27680", "27684", "27685", "27686", "27687", "27688", "27690", "27692", "27693", "27697", "27698", "27701", "27703", "27705", "27710", "27711", "27714", "27716", "27717", "27718", "27720", "27721", "27722", "27723", "27724", "27725", "27727", "27729", "27730", "27731", "27734", "27736", "27741", "27742", "27743", "27745", "27746", "27749", "27751", "27755", "27756", "27757", "27760", "27762", "27764", "27771", "27773", "27774", "27775", "27776", "27777", "27779", "27780", "27782", "27783", "27785", "27786", "27787", "27789", "27791", "27794", "27796", "27798", "27800", "27802", "27803", "27808", "27809", "27810", "27816", "27818", "27821", "27822", "27823", "27825", "27826", "27828", "27831", "27834", "27835", "27838", "27839", "27841", "27842", "27844", "27846", "27847", "27849", "27851", "27852", "27854", "27855", "27857", "27863", "27864", "27866", "27867", "27868", "27869", "27870", "27872", "27873", "27876", "27878", "27879", "27881", "27882", "27885", "27886", "27887", "27894", "27897", "27899", "27900", "27901", "27903", "27905", "27906", "27907", "27909", "27911", "27913", "27916", "27918", "27920", "27921", "27923", "27927", "27929", "27930", "27931", "27934", "27936", "27943", "27944", "27946", "27947", "27948", "27950", "27951", "27957", "27959", "27960", "27961", "27962", "27965", "27969", "27973", "27974", "27975", "27976", "27979", "27981", "27985", "27994", "27995", "27999", "28002", "28004", "28005", "28006", "28007", "28008", "28009", "28010", "28011", "28012", "28013", "28016", "28017", "28018", "28020", "28024", "28025", "28026", "28028", "28029", "28030", "28031", "28032", "28035", "28039", "28041", "28043", "28044", "28048", "28050", "28051", "28053", "28055", "28057", "28058", "28063", "28067", "28072", "28074", "28075", "28076", "28078", "28080", "28082", "28083", "28086", "28087", "28094", "28096", "28097", "28100", "28101", "28106", "28107", "28109", "28110", "28111", "28112", "28115", "28117", "28119", "28124", "28126", "28127", "28129", "28130", "28132", "28133", "28134", "28137", "28140", "28141", "28144", "28147", "28148", "28149", "28151", "28154", "28155", "28156", "28157", "28158", "28159", "28166", "28167", "28168", "28170", "28172", "28173", "28175", "28176", "28178", "28180", "28182", "28183", "28184", "28186", "28189", "28190", "28192", "28194", "28197", "28200", "28202", "28204", "28205", "28206", "28210", "28213", "28215", "28217", "28219", "28221", "28222", "28223", "28225", "28226", "28228", "28229", "28231", "28232", "28233", "28235", "28238", "28239", "28241", "28242", "28244", "28247", "28249", "28250", "28253", "28255", "28257", "28261", "28262", "28266", "28268", "28269", "28270", "28271", "28273", "28274", "28275", "28277", "28278", "28281", "28282", "28283", "28285", "28290", "28291", "28292", "28293", "28294", "28299", "28301", "28302", "28304", "28305", "28306", "28311", "28319", "28321", "28322", "28323", "28324", "28326", "28329", "28332", "28334", "28340", "28342", "28346", "28347", "28348", "28350", "28351", "28353", "28356", "28357", "28358", "28360", "28361", "28363", "28365", "28366", "28368", "28371", "28374", "28377", "28378", "28381", "28385", "28386", "28390", "28391", "28392", "28393", "28397", "28398", "28401", "28402", "28404", "28407", "28408", "28409", "28410", "28411", "28414", "28415", "28416", "28417", "28418", "28419", "28422", "28425", "28426", "28428", "28432", "28433", "28434", "28435", "28436", "28437", "28439", "28444", "28446", "28448", "28449", "28450", "28451", "28454", "28457", "28458", "28459", "28461", "28462", "28463", "28464", "28466", "28469", "28470", "28472", "28473", "28476", "28477", "28479", "28480", "28481", "28483", "28485", "28487", "28489", "28492", "28493", "28497", "28498", "28500", "28501", "28502", "28505", "28508", "28509", "28510", "28512", "28513", "28514", "28515", "28518", "28528", "28529", "28533", "28534", "28536", "28537", "28539", "28541", "28542", "28544", "28547", "28548", "28549", "28550", "28552", "28554", "28557", "28558", "28560", "28561", "28562", "28564", "28568", "28569", "28573", "28575", "28577", "28582", "28584", "28588", "28600", "28601", "28602", "28603", "28604", "28607", "28608", "28612", "28613", "28617", "28621", "28623", "28625", "28627", "28630", "28631", "28632", "28636", "28637", "28638", "28641", "28643", "28646", "28647", "28650", "28651", "28656", "28659", "28660", "28661", "28662", "28663", "28665", "28666", "28668", "28669", "28673", "28675", "28681", "28683", "28684", "28685", "28689", "28690", "28692", "28693", "28698", "28700", "28702", "28704", "28705", "28707", "28708", "28709", "28710", "28711", "28713", "28714", "28715", "28716", "28720", "28721", "28724", "28726", "28727", "28728", "28731", "28732", "28733", "28734", "28736", "28739", "28742", "28744", "28746", "28750", "28755", "28758", "28759", "28760", "28762", "28764", "28768", "28770", "28771", "28775", "28777", "28778", "28782", "28784", "28786", "28787", "28788", "28791", "28793", "28796", "28798", "28799", "28800", "28801", "28802", "28805", "28807", "28809", "28810", "28811", "28816", "28819", "28821", "28822", "28833", "28834", "28835", "28839", "28843", "28845", "28846", "28848", "28849", "28850", "28856", "28858", "28860", "28866", "28867", "28868", "28875", "28877", "28878", "28879", "28881", "28882", "28883", "28884", "28885", "28888", "28892", "28894", "28895", "28897", "28898", "28900", "28901", "28904", "28909", "28910", "28911", "28912", "28915", "28918", "28919", "28923", "28927", "28930", "28933", "28934", "28935", "28936", "28937", "28939", "28940", "28948", "28950", "28959", "28960", "28961", "28963", "28970", "28972", "28974", "28979", "28980", "28982", "28983", "28988", "28992", "28993", "28999", "29004", "29006", "29007", "29009", "29010", "29011", "29013", "29016", "29018", "29020", "29026", "29027", "29028", "29029", "29030", "29033", "29035", "29036", "29037", "29038", "29039", "29043", "29044", "29046", "29049", "29052", "29053", "29054", "29055", "29056", "29061", "29064", "29068", "29071", "29074", "29077", "29081", "29082", "29083", "29084", "29085", "29086", "29087", "29088", "29090", "29091", "29096", "29097", "29098", "29100", "29102", "29104", "29107", "29109", "29111", "29114", "29115", "29116", "29117", "29118", "29119", "29120", "29126", "29127", "29135", "29137", "29139", "29141", "29142", "29151", "29152", "29154", "29155", "29158", "29159", "29161", "29162", "29166", "29168", "29169", "29172", "29175", "29179", "29182", "29185", "29187", "29189", "29190", "29191", "29192", "29195", "29196", "29198", "29199", "29200", "29201", "29204", "29207", "29210", "29213", "29215", "29216", "29222", "29223", "29224", "29226", "29227", "29228", "29229", "29230", "29231", "29232", "29234", "29239", "29243", "29245", "29247", "29249", "29256", "29258", "29259", "29262", "29265", "29266", "29268", "29269", "29270", "29272", "29273", "29275", "29276", "29277", "29280", "29283", "29284", "29285", "29288", "29289", "29290", "29291", "29297", "29298", "29299", "29300", "29301", "29302", "29303", "29304", "29309", "29318", "29320", "29321", "29322", "29325", "29328", "29329", "29332", "29333", "29334", "29336", "29337", "29338", "29339", "29342", "29345", "29350", "29351", "29354", "29356", "29358", "29360", "29366", "29369", "29370", "29375", "29376", "29378", "29379", "29383", "29384", "29385", "29388", "29392", "29393", "29394", "29397", "29400", "29401", "29402", "29404", "29408", "29410", "29412", "29413", "29414", "29415", "29416", "29423", "29425", "29427", "29428", "29430", "29431", "29432", "29433", "29435", "29440", "29441", "29442", "29443", "29445", "29446", "29452", "29454", "29455", "29459", "29460", "29462", "29463", "29465", "29466", "29467", "29470", "29472", "29473", "29474", "29475", "29477", "29478", "29479", "29480", "29482", "29485", "29490", "29491", "29493", "29495", "29497", "29498", "29501", "29505", "29506", "29507", "29509", "29511", "29512", "29513", "29515", "29516", "29517", "29519", "29520", "29521", "29522", "29525", "29526", "29529", "29531", "29532", "29537", "29538", "29542", "29543", "29548", "29549", "29550", "29551", "29553", "29555", "29558", "29559", "29562", "29564", "29565", "29566", "29567", "29570", "29573", "29574", "29575", "29577", "29579", "29580", "29581", "29582", "29584", "29586", "29587", "29589", "29591", "29592", "29594", "29597", "29599", "29601", "29603", "29604", "29605", "29606", "29608", "29611", "29612", "29613", "29615", "29616", "29618", "29619", "29620", "29621", "29626", "29628", "29632", "29636", "29637", "29639", "29640", "29641", "29642", "29643", "29648", "29649", "29650", "29653", "29654", "29655", "29657", "29660", "29661", "29662", "29663", "29664", "29670", "29673", "29677", "29678", "29680", "29681", "29684", "29685", "29686", "29687", "29689", "29692", "29695", "29696", "29697", "29699", "29700", "29702", "29703", "29705", "29706", "29707", "29711", "29715", "29717", "29719", "29722", "29725", "29726", "29727", "29728", "29730", "29731", "29732", "29733", "29735", "29737", "29741", "29743", "29745", "29746", "29747", "29748", "29749", "29752", "29753", "29754", "29757", "29758", "29760", "29762", "29766", "29768", "29770", "29773", "29775", "29778", "29779", "29781", "29782", "29787", "29792", "29793", "29795", "29796", "29798", "29799", "29800", "29801", "29802", "29803", "29804", "29807", "29810", "29813", "29816", "29817", "29818", "29819", "29820", "29821", "29822", "29823", "29824", "29828", "29829", "29830", "29832", "29834", "29835", "29836", "29838", "29840", "29841", "29842", "29843", "29844", "29851", "29853", "29857", "29858", "29859", "29860", "29861", "29862", "29865", "29866", "29868", "29871", "29872", "29873", "29874", "29876", "29882", "29884", "29888", "29889", "29891", "29892", "29894", "29895", "29896", "29900", "29901", "29902", "29904", "29905", "29907", "29908", "29909", "29910", "29913", "29915", "29916", "29917", "29918", "29920", "29924", "29926", "29927", "29932", "29933", "29935", "29936", "29937", "29939", "29943", "29945", "29948", "29950", "29951", "29952", "29953", "29954", "29955", "29957", "29960", "29961", "29964", "29965", "29966", "29967", "29968", "29972", "29974", "29976", "29977", "29979", "29980", "29981", "29985", "29987", "29988", "29989", "29993", "29994", "29995", "29997", "29998", "30000", "30003", "30004", "30005", "30007", "30009", "30012", "30013", "30014", "30015", "30018", "30019", "30020", "30021", "30023", "30025", "30026", "30028", "30029", "30030", "30031", "30032", "30033", "30034", "30036", "30037", "30038", "30039", "30041", "30042", "30046", "30048", "30050", "30051", "30052", "30054", "30055", "30058", "30060", "30061", "30064", "30066", "30068", "30075", "30082", "30084", "30087", "30088", "30089", "30090", "30091", "30092", "30094", "30095", "30096", "30097", "30100", "30101", "30105", "30109", "30111", "30112", "30113", "30114", "30115", "30119", "30121", "30123", "30126", "30127", "30133", "30135", "30137", "30138", "30139", "30141", "30143", "30146", "30147", "30151", "30157", "30161", "30164", "30174", "30176", "30178", "30181", "30183", "30186", "30188", "30190", "30191", "30192", "30193", "30197", "30200", "30202", "30205", "30207", "30212", "30216", "30217", "30222", "30223", "30224", "30225", "30226", "30227", "30228", "30229", "30230", "30231", "30237", "30240", "30241", "30243", "30245", "30248", "30250", "30251", "30252", "30254", "30255", "30256", "30257", "30262", "30264", "30265", "30268", "30273", "30276", "30278", "30279", "30282", "30283", "30284", "30286", "30288", "30290", "30291", "30292", "30293", "30296", "30297", "30298", "30300", "30301", "30302", "30304", "30305", "30306", "30308", "30309", "30312", "30315", "30317", "30319", "30320", "30322", "30323", "30330", "30332", "30333", "30337", "30339", "30342", "30344", "30348", "30349", "30350", "30354", "30355", "30357", "30358", "30359", "30361", "30363", "30371", "30375", "30377", "30379", "30380", "30383", "30384", "30385", "30387", "30389", "30391", "30392", "30393", "30394", "30395", "30396", "30404", "30405", "30407", "30408", "30409", "30411", "30412", "30413", "30415", "30416", "30418", "30420", "30421", "30423", "30424", "30426", "30427", "30428", "30429", "30431", "30432", "30433", "30436", "30438", "30444", "30450", "30454", "30459", "30466", "30467", "30468", "30469", "30471", "30472", "30474", "30477", "30481", "30482", "30483", "30486", "30487", "30489", "30490", "30491", "30494", "30495", "30498", "30499", "30500", "30502", "30503", "30506", "30508", "30509", "30510", "30515", "30517", "30520", "30522", "30524", "30525", "30526", "30528", "30529", "30532", "30535", "30536", "30539", "30540", "30542", "30545", "30546", "30552", "30553", "30556", "30558", "30559", "30560", "30564", "30565", "30567", "30568", "30570", "30572", "30573", "30574", "30578", "30579", "30580", "30582", "30584", "30585", "30587", "30595", "30596", "30597", "30598", "30600", "30601", "30605", "30607", "30611", "30613", "30615", "30617", "30618", "30620", "30622", "30623", "30627", "30629", "30631", "30632", "30633", "30635", "30638", "30640", "30641", "30646", "30647", "30650", "30651", "30652", "30653", "30656", "30657", "30662", "30663", "30664", "30665", "30666", "30668", "30671", "30673", "30674", "30681", "30684", "30686", "30689", "30691", "30692", "30693", "30695", "30696", "30698", "30699", "30700", "30702", "30703", "30705", "30706", "30707", "30712", "30713", "30714", "30715", "30718", "30721", "30722", "30725", "30726", "30727", "30728", "30729", "30731", "30732", "30733", "30735", "30736", "30738", "30743", "30744", "30746", "30748", "30751", "30754", "30757", "30761", "30762", "30763", "30764", "30767", "30768", "30769", "30770", "30773", "30777", "30779", "30780", "30783", "30788", "30790", "30794", "30796", "30797", "30798", "30801", "30802", "30803", "30810", "30811", "30812", "30814", "30815", "30816", "30817", "30819", "30822", "30823", "30824", "30826", "30831", "30832", "30833", "30834", "30835", "30836", "30840", "30841", "30842", "30843", "30846", "30849", "30850", "30852", "30853", "30854", "30855", "30856", "30858", "30859", "30863", "30864", "30865", "30866", "30867", "30868", "30869", "30871", "30872", "30874", "30877", "30881", "30882", "30883", "30884", "30896", "30897", "30898", "30899", "30900", "30901", "30902", "30903", "30907", "30909", "30911", "30912", "30914", "30915", "30918", "30919", "30921", "30922", "30927", "30928", "30930", "30938", "30942", "30943", "30946", "30947", "30948", "30949", "30950", "30951", "30954", "30955", "30957", "30958", "30959", "30960", "30963", "30964", "30965", "30966", "30969", "30974", "30976", "30979", "30981", "30982", "30983", "30985", "30986", "30988", "30989", "30990", "30991", "30995", "30996", "30997", "30998", "30999", "31003", "31005", "31008", "31009", "31011", "31013", "31015", "31017", "31018", "31019", "31021", "31022", "31023", "31024", "31025", "31027", "31030", "31033", "31034", "31035", "31037", "31039", "31040", "31041", "31042", "31043", "31044", "31046", "31048", "31050", "31054", "31055", "31056", "31057", "31060", "31061", "31065", "31067", "31068", "31069", "31070", "31071", "31072", "31075", "31076", "31077", "31078", "31082", "31084", "31085", "31087", "31088", "31090", "31097", "31100", "31104", "31107", "31110", "31111", "31112", "31113", "31116", "31117", "31118", "31120", "31123", "31124", "31125", "31128", "31130", "31132", "31134", "31136", "31138", "31140", "31143", "31146", "31147", "31148", "31150", "31152", "31154", "31155", "31156", "31158", "31162", "31163", "31165", "31168", "31169", "31171", "31173", "31174", "31176", "31178", "31179", "31180", "31183", "31185", "31186", "31191", "31193", "31195", "31196", "31207", "31208", "31209", "31216", "31217", "31220", "31221", "31224", "31225", "31227", "31228", "31229", "31233", "31234", "31237", "31238", "31240", "31244", "31245", "31246", "31247", "31248", "31251", "31252", "31254", "31255", "31256", "31257", "31260", "31261", "31263", "31264", "31265", "31267", "31268", "31271", "31272", "31274", "31275", "31277", "31278", "31281", "31284", "31287", "31290", "31291", "31292", "31293", "31295", "31298", "31300", "31301", "31303", "31305", "31307", "31308", "31312", "31313", "31316", "31317", "31320", "31322", "31323", "31327", "31329", "31330", "31331", "31332", "31334", "31335", "31339", "31341", "31342", "31351", "31352", "31353", "31354", "31356", "31357", "31358", "31360", "31361", "31362", "31364", "31365", "31366", "31371", "31375", "31377", "31379", "31380", "31383", "31384", "31387", "31390", "31393", "31395", "31396", "31397", "31402", "31404", "31405", "31408", "31412", "31414", "31416", "31417", "31419", "31420", "31421", "31423", "31430", "31431", "31433", "31435", "31437", "31439", "31440", "31442", "31447", "31448", "31449", "31451", "31455", "31456", "31460", "31462", "31464", "31467", "31470", "31471", "31473", "31475", "31476", "31477", "31479", "31481", "31483", "31486", "31488", "31490", "31491", "31496", "31498", "31499", "31502", "31503", "31504", "31506", "31507", "31509", "31510", "31511", "31512", "31514", "31516", "31518", "31520", "31522", "31524", "31525", "31526", "31527", "31529", "31530", "31532", "31534", "31535", "31536", "31540", "31541", "31542", "31543", "31544", "31545", "31547", "31549", "31551", "31552", "31554", "31556", "31559", "31560", "31563", "31565", "31569", "31570", "31571", "31572", "31573", "31574", "31575", "31576", "31577", "31578", "31579", "31583", "31584", "31587", "31591", "31592", "31593", "31594", "31598", "31599", "31600", "31601", "31602", "31603", "31605", "31608", "31609", "31610", "31613", "31615", "31617", "31618", "31620", "31623", "31624", "31625", "31630", "31632", "31634", "31635", "31636", "31638", "31640", "31641", "31642", "31644", "31645", "31648", "31649", "31650", "31651", "31653", "31656", "31657", "31658", "31659", "31664", "31667", "31668", "31670", "31672", "31677", "31679", "31680", "31683", "31684", "31685", "31686", "31687", "31688", "31693", "31694", "31695", "31696", "31697", "31699", "31700", "31702", "31704", "31707", "31708", "31710", "31711", "31712", "31717", "31718", "31722", "31724", "31729", "31731", "31735", "31736", "31737", "31741", "31742", "31746", "31748", "31749", "31750", "31752", "31754", "31755", "31757", "31758", "31763", "31764", "31765", "31767", "31774", "31775", "31776", "31777", "31778", "31779", "31780", "31782", "31783", "31784", "31786", "31788", "31791", "31794", "31796", "31799", "31801", "31802", "31803", "31804", "31805", "31806", "31807", "31809", "31811", "31812", "31813", "31814", "31816", "31817", "31818", "31821", "31822", "31823", "31824", "31825", "31826", "31828", "31829", "31831", "31832", "31833", "31838", "31839", "31840", "31842", "31843", "31846", "31849", "31855", "31860", "31861", "31862", "31863", "31864", "31865", "31867", "31868", "31870", "31871", "31873", "31874", "31883", "31884", "31885", "31886", "31887", "31888", "31890", "31892", "31894", "31895", "31899", "31900", "31905", "31906", "31908", "31910", "31912", "31914", "31916", "31917", "31918", "31920", "31921", "31922", "31929", "31930", "31931", "31933", "31935", "31936", "31937", "31939", "31944", "31945", "31946", "31947", "31948", "31949", "31950", "31951", "31954", "31955", "31956", "31958", "31960", "31962", "31963", "31964", "31965", "31966", "31967", "31969", "31971", "31973", "31975", "31978", "31979", "31981", "31982", "31985", "31987", "31988", "31990", "31991", "31992", "31993", "31996", "31997", "31999", "32000", "32001", "32002", "32003", "32004", "32006", "32007", "32008", "32009", "32012", "32013", "32014", "32015", "32017", "32020", "32021", "32022", "32024", "32025", "32031", "32032", "32035", "32037", "32040", "32041", "32043", "32044", "32046", "32047", "32049", "32051", "32052", "32054", "32055", "32056", "32057", "32058", "32059", "32060", "32064", "32066", "32069", "32070", "32072", "32078", "32079", "32083", "32085", "32086", "32087", "32089", "32093", "32094", "32097", "32101", "32108", "32111", "32113", "32115", "32116", "32117", "32118", "32119", "32121", "32125", "32129", "32130", "32131", "32135", "32136", "32138", "32139", "32140", "32141", "32143", "32144", "32145", "32146", "32148", "32151", "32152", "32155", "32156", "32157", "32158", "32160", "32161", "32164", "32166", "32167", "32172", "32173", "32175", "32177", "32178", "32182", "32183", "32184", "32186", "32187", "32189", "32190", "32191", "32192", "32193", "32194", "32196", "32198", "32206", "32207", "32210", "32215", "32216", "32217", "32222", "32225", "32226", "32227", "32229", "32230", "32231", "32232", "32234", "32237", "32241", "32242", "32251", "32252", "32253", "32254", "32255", "32257", "32259", "32261", "32262", "32264", "32265", "32268", "32269", "32271", "32273", "32275", "32277", "32279", "32280", "32281", "32282", "32283", "32286", "32288", "32290", "32291", "32293", "32294", "32296", "32299", "32300", "32306", "32308", "32309", "32311", "32319", "32320", "32322", "32323", "32324", "32325", "32327", "32331", "32335", "32336", "32337", "32341", "32342", "32343", "32346", "32347", "32348", "32349", "32350", "32352", "32354", "32357", "32362", "32366", "32367", "32369", "32370", "32371", "32373", "32378", "32380", "32381", "32382", "32383", "32386", "32391", "32392", "32395", "32396", "32397", "32399", "32400", "32401", "32404", "32407", "32408", "32409", "32413", "32416", "32417", "32419", "32425", "32426", "32427", "32430", "32436", "32438", "32442", "32443", "32444", "32445", "32446", "32447", "32452", "32453", "32454", "32457", "32458", "32460", "32461", "32462", "32464", "32468", "32470", "32473", "32477", "32478", "32486", "32487", "32489", "32491", "32493", "32494", "32498", "32500", "32503", "32504", "32506", "32507", "32510", "32512", "32513", "32516", "32518", "32523", "32524", "32525", "32526", "32528", "32529", "32530", "32531", "32533", "32536", "32537", "32538", "32539", "32541", "32547", "32553", "32556", "32557", "32558", "32559", "32560", "32561", "32563", "32564", "32566", "32567", "32568", "32571", "32573", "32574", "32579", "32580", "32581", "32582", "32583", "32585", "32587", "32588", "32589", "32590", "32595", "32597", "32598", "32602", "32603", "32605", "32606", "32607", "32608", "32610", "32611", "32614", "32617", "32618", "32619", "32622", "32624", "32625", "32627", "32629", "32633", "32634", "32638", "32644", "32645", "32646", "32651", "32652", "32655", "32659", "32663", "32664", "32665", "32669", "32670", "32671", "32672", "32673", "32674", "32675", "32678", "32680", "32681", "32683", "32684", "32685", "32686", "32689", "32691", "32696", "32698", "32699", "32700", "32702", "32703", "32707", "32708", "32710", "32711", "32713", "32714", "32716", "32718", "32719", "32720", "32723", "32724", "32730", "32732", "32735", "32736", "32737", "32739", "32742", "32744", "32748", "32751", "32752", "32753", "32754", "32755", "32756", "32757", "32758", "32761", "32763", "32768", "32769", "32770", "32771", "32772", "32774", "32776", "32777", "32778", "32785", "32786", "32789", "32790", "32791", "32795", "32796", "32798", "32800", "32801", "32809", "32810", "32811", "32812", "32816", "32817", "32822", "32823", "32824", "32825", "32826", "32830", "32835", "32836", "32837", "32838", "32840", "32843", "32845", "32846", "32847", "32848", "32849", "32851", "32853", "32856", "32858", "32864", "32867", "32868", "32869", "32872", "32875", "32877", "32879", "32880", "32883", "32884", "32887", "32888", "32889", "32890", "32891", "32892", "32896", "32897", "32898", "32899", "32903", "32905", "32907", "32908", "32910", "32913", "32914", "32915", "32919", "32920", "32922", "32923", "32927", "32930", "32931", "32934", "32935", "32939", "32941", "32942", "32943", "32944", "32946", "32952", "32953", "32954", "32957", "32959", "32962", "32964", "32968", "32971", "32972", "32974", "32978", "32981", "32984", "32985", "32987", "32991", "32993", "32995", "32997", "32999", "33001", "33002", "33003", "33006", "33008", "33010", "33012", "33016", "33017", "33018", "33023", "33024", "33026", "33029", "33032", "33035", "33038", "33040", "33044", "33048", "33053", "33059", "33062", "33063", "33065", "33070", "33071", "33072", "33073", "33074", "33075", "33076", "33080", "33084", "33085", "33088", "33089", "33090", "33091", "33093", "33095", "33099", "33101", "33104", "33108", "33109", "33112", "33113", "33114", "33115", "33117", "33124", "33126", "33127", "33131", "33132", "33136", "33137", "33140", "33143", "33144", "33145", "33149", "33150", "33151", "33152", "33155", "33156", "33157", "33158", "33159", "33161", "33162", "33163", "33164", "33165", "33172", "33176", "33180", "33182", "33183", "33184", "33185", "33188", "33190", "33191", "33194", "33195", "33196", "33197", "33198", "33202", "33204", "33205", "33208", "33211", "33213", "33218", "33219", "33220", "33222", "33223", "33226", "33228", "33229", "33231", "33232", "33233", "33234", "33235", "33239", "33241", "33243", "33246", "33249", "33250", "33253", "33254", "33255", "33256", "33257", "33258", "33260", "33264", "33266", "33269", "33274", "33276", "33278", "33279", "33283", "33284", "33289", "33292", "33293", "33299", "33302", "33305", "33306", "33308", "33309", "33310", "33312", "33313", "33316", "33322", "33325", "33330", "33334", "33335", "33337", "33339", "33341", "33342", "33343", "33347", "33349", "33350", "33352", "33353", "33354", "33356", "33357", "33359", "33360", "33362", "33363", "33365", "33368", "33369", "33370", "33372", "33374", "33379", "33380", "33381", "33384", "33386", "33387", "33389", "33392", "33394", "33395", "33396", "33397", "33398", "33399", "33400", "33401", "33406", "33408", "33411", "33412", "33413", "33415", "33417", "33419", "33422", "33426", "33427", "33429", "33433", "33434", "33435", "33437", "33442", "33444", "33446", "33448", "33450", "33451", "33453", "33455", "33456", "33457", "33458", "33459", "33460", "33461", "33462", "33463", "33464", "33466", "33468", "33470", "33471", "33472", "33474", "33475", "33476", "33477", "33478", "33480", "33482", "33486", "33488", "33489", "33490", "33492", "33493", "33495", "33496", "33502", "33503", "33506", "33507", "33508", "33510", "33512", "33513", "33514", "33516", "33520", "33521", "33525", "33526", "33535", "33536", "33537", "33538", "33540", "33541", "33545", "33548", "33549", "33551", "33555", "33557", "33560", "33562", "33563", "33566", "33569", "33570", "33574", "33575", "33576", "33577", "33579", "33580", "33581", "33582", "33583", "33585", "33587", "33590", "33591", "33592", "33595", "33596", "33598", "33603", "33604", "33608", "33610", "33611", "33614", "33615", "33616", "33618", "33623", "33625", "33627", "33629", "33632", "33634", "33635", "33636", "33637", "33638", "33639", "33640", "33643", "33645", "33646", "33647", "33650", "33652", "33655", "33658", "33660", "33663", "33664", "33666", "33667", "33669", "33672", "33674", "33681", "33685", "33686", "33688", "33691", "33697", "33698", "33700", "33705", "33708", "33709", "33714", "33715", "33716", "33717", "33719", "33724", "33728", "33730", "33732", "33734", "33736", "33737", "33738", "33739", "33743", "33744", "33745", "33746", "33747", "33748", "33749", "33750", "33753", "33754", "33756", "33757", "33758", "33762", "33763", "33764", "33767", "33769", "33771", "33772", "33774", "33775", "33777", "33778", "33781", "33782", "33783", "33784", "33786", "33787", "33788", "33789", "33790", "33791", "33792", "33794", "33795", "33796", "33802", "33803", "33804", "33806", "33808", "33809", "33810", "33811", "33812", "33813", "33815", "33816", "33817", "33819", "33820", "33821", "33822", "33824", "33825", "33827", "33828", "33832", "33835", "33838", "33839", "33841", "33842", "33844", "33845", "33847", "33848", "33852", "33853", "33856", "33857", "33858", "33860", "33861", "33864", "33865", "33868", "33874", "33876", "33878", "33879", "33880", "33881", "33882", "33885", "33886", "33887", "33889", "33892", "33895", "33896", "33897", "33900", "33901", "33902", "33903", "33904", "33911", "33912", "33915", "33916", "33918", "33919", "33920", "33921", "33922", "33925", "33926", "33927", "33928", "33929", "33932", "33934", "33935", "33937", "33939", "33940", "33942", "33943", "33944", "33947", "33948", "33949", "33950", "33952", "33953", "33955", "33957", "33960", "33962", "33964", "33967", "33969", "33972", "33975", "33976", "33977", "33979", "33980", "33981", "33982", "33983", "33985", "33986", "33989", "33991", "33996", "33998", "34001", "34005", "34006", "34007", "34008", "34009", "34015", "34016", "34018", "34020", "34021", "34027", "34028", "34031", "34032", "34033", "34035", "34036", "34037", "34038", "34040", "34042", "34045", "34048", "34050", "34051", "34052", "34053", "34054", "34058", "34060", "34061", "34062", "34063", "34064", "34066", "34067", "34068", "34069", "34070", "34071", "34073", "34074", "34075", "34076", "34077", "34078", "34079", "34080", "34082", "34083", "34087", "34090", "34091", "34092", "34093", "34095", "34100", "34101", "34103", "34105", "34112", "34114", "34115", "34116", "34117", "34123", "34124", "34127", "34130", "34131", "34132", "34135", "34137", "34138", "34139", "34146", "34147", "34148", "34149", "34150", "34153", "34156", "34158", "34160", "34163", "34164", "34169", "34170", "34174", "34176", "34180", "34181", "34182", "34183", "34184", "34186", "34187", "34188", "34189", "34193", "34198", "34199", "34200", "34201", "34202", "34203", "34204", "34207", "34216", "34220", "34222", "34223", "34226", "34229", "34230", "34231", "34236", "34244", "34245", "34246", "34251", "34252", "34253", "34254", "34256", "34257", "34259", "34261", "34262", "34263", "34265", "34266", "34269", "34270", "34271", "34273", "34274", "34275", "34277", "34278", "34279", "34281", "34282", "34284", "34286", "34288", "34289", "34295", "34296", "34298", "34303", "34305", "34306", "34310", "34314", "34316", "34320", "34321", "34324", "34328", "34332", "34333", "34334", "34335", "34336", "34338", "34339", "34340", "34343", "34344", "34347", "34351", "34352", "34353", "34354", "34358", "34359", "34360", "34361", "34363", "34364", "34365", "34371", "34372", "34373", "34376", "34383", "34384", "34385", "34387", "34388", "34391", "34393", "34394", "34396", "34398", "34399", "34401", "34403", "34404", "34405", "34407", "34412", "34417", "34419", "34422", "34425", "34427", "34428", "34430", "34432", "34433", "34436", "34438", "34441", "34442", "34444", "34447", "34448", "34454", "34457", "34461", "34462", "34464", "34465", "34466", "34467", "34469", "34472", "34473", "34475", "34476", "34477", "34485", "34488", "34489", "34491", "34492", "34497", "34500", "34501", "34502", "34505", "34508", "34511", "34512", "34513", "34514", "34516", "34519", "34521", "34524", "34526", "34528", "34529", "34530", "34531", "34534", "34536", "34538", "34539", "34540", "34541", "34544", "34545", "34548", "34549", "34551", "34552", "34555", "34560", "34562", "34563", "34564", "34566", "34567", "34570", "34572", "34577", "34579", "34582", "34583", "34585", "34586", "34587", "34589", "34596", "34598", "34599", "34600", "34602", "34609", "34612", "34614", "34619", "34623", "34624", "34625", "34628", "34632", "34633", "34636", "34637", "34638", "34639", "34641", "34642", "34646", "34647", "34650", "34655", "34656", "34657", "34658", "34659", "34660", "34661", "34662", "34663", "34664", "34665", "34667", "34669", "34673", "34674", "34675", "34678", "34679", "34680", "34684", "34687", "34696", "34697", "34698", "34702", "34704", "34706", "34709", "34711", "34714", "34717", "34719", "34722", "34723", "34725", "34726", "34729", "34730", "34731", "34733", "34736", "34740", "34741", "34742", "34743", "34744", "34745", "34749", "34751", "34752", "34753", "34754", "34756", "34760", "34763", "34764", "34765", "34766", "34767", "34768", "34770", "34773", "34774", "34776", "34781", "34782", "34784", "34787", "34789", "34792", "34794", "34797", "34800", "34801", "34802", "34804", "34806", "34807", "34811", "34812", "34813", "34815", "34816", "34818", "34819", "34821", "34822", "34823", "34824", "34826", "34828", "34829", "34831", "34834", "34835", "34841", "34843", "34844", "34847", "34848", "34850", "34851", "34852", "34853", "34855", "34856", "34858", "34859", "34862", "34863", "34867", "34868", "34869", "34870", "34873", "34874", "34876", "34877", "34878", "34882", "34884", "34887", "34889", "34890", "34891", "34893", "34898", "34900", "34901", "34902", "34903", "34904", "34908", "34909", "34910", "34915", "34916", "34919", "34920", "34924", "34927", "34930", "34933", "34937", "34938", "34939", "34940", "34941", "34942", "34944", "34945", "34949", "34951", "34953", "34956", "34957", "34959", "34960", "34963", "34964", "34965", "34970", "34972", "34973", "34974", "34975", "34978", "34980", "34987", "34990", "34991", "34993", "34999", "35000", "35003", "35004", "35005", "35006", "35008", "35009", "35012", "35014", "35017", "35019", "35020", "35021", "35023", "35027", "35029", "35030", "35031", "35032", "35033", "35035", "35037", "35038", "35039", "35043", "35044", "35045", "35046", "35048", "35049", "35050", "35051", "35053", "35054", "35057", "35061", "35063", "35064", "35066", "35067", "35069", "35070", "35071", "35072", "35076", "35079", "35081", "35084", "35085", "35086", "35089", "35090", "35091", "35092", "35093", "35094", "35095", "35098", "35099", "35103", "35105", "35108", "35109", "35113", "35122", "35123", "35124", "35125", "35129", "35130", "35131", "35132", "35135", "35136", "35139", "35140", "35143", "35144", "35146", "35148", "35152", "35154", "35156", "35159", "35161", "35162", "35163", "35164", "35166", "35167", "35168", "35169", "35170", "35171", "35172", "35173", "35178", "35179", "35181", "35186", "35188", "35190", "35195", "35196", "35198", "35199", "35200", "35201", "35204", "35205", "35212", "35219", "35220", "35224", "35225", "35229", "35230", "35231", "35233", "35234", "35235", "35237", "35242", "35244", "35246", "35247", "35250", "35251", "35252", "35254", "35256", "35258", "35263", "35264", "35266", "35272", "35275", "35276", "35277", "35279", "35282", "35283", "35286", "35287", "35288", "35295", "35296", "35298", "35299", "35300", "35304", "35307", "35309", "35311", "35313", "35314", "35316", "35318", "35319", "35320", "35321", "35322", "35323", "35324", "35325", "35328", "35329", "35330", "35334", "35338", "35339", "35341", "35343", "35344", "35348", "35349", "35350", "35358", "35361", "35362", "35364", "35369", "35371", "35373", "35374", "35375", "35379", "35380", "35382", "35384", "35386", "35387", "35388", "35391", "35392", "35394", "35395", "35398", "35399", "35402", "35403", "35405", "35409", "35414", "35416", "35418", "35419", "35420", "35421", "35422", "35427", "35431", "35432", "35433", "35434", "35436", "35439", "35440", "35442", "35443", "35444", "35445", "35446", "35447", "35451", "35455", "35457", "35458", "35459", "35463", "35465", "35468", "35469", "35472", "35473", "35480", "35481", "35482", "35484", "35488", "35490", "35491", "35494", "35495", "35496", "35502", "35503", "35505", "35507", "35508", "35510", "35513", "35515", "35516", "35517", "35519", "35520", "35521", "35522", "35523", "35524", "35526", "35528", "35529", "35530", "35531", "35534", "35537", "35542", "35543", "35544", "35548", "35549", "35550", "35555", "35556", "35557", "35558", "35560", "35561", "35562", "35566", "35571", "35572", "35573", "35574", "35578", "35581", "35583", "35586", "35588", "35594", "35595", "35597", "35598", "35599", "35600", "35605", "35607", "35609", "35611", "35613", "35614", "35617", "35620", "35621", "35626", "35628", "35630", "35632", "35635", "35636", "35637", "35638", "35646", "35648", "35649", "35654", "35655", "35656", "35657", "35659", "35663", "35664", "35668", "35669", "35671", "35672", "35673", "35677", "35678", "35681", "35682", "35683", "35684", "35685", "35687", "35688", "35689", "35691", "35692", "35696", "35697", "35698", "35699", "35700", "35702", "35703", "35706", "35712", "35714", "35716", "35718", "35720", "35724", "35725", "35726", "35727", "35728", "35729", "35736", "35743", "35746", "35747", "35751", "35753", "35754", "35757", "35762", "35763", "35764", "35765", "35766", "35767", "35768", "35772", "35775", "35778", "35779", "35781", "35782", "35785", "35792", "35794", "35798", "35799", "35802", "35803", "35804", "35805", "35807", "35814", "35815", "35816", "35817", "35818", "35825", "35826", "35829", "35832", "35835", "35836", "35838", "35839", "35841", "35842", "35843", "35846", "35847", "35848", "35849", "35850", "35851", "35852", "35853", "35854", "35855", "35856", "35859", "35861", "35863", "35864", "35865", "35866", "35868", "35870", "35872", "35876", "35879", "35880", "35881", "35882", "35883", "35884", "35885", "35887", "35889", "35891", "35892", "35893", "35895", "35898", "35900", "35902", "35908", "35910", "35911", "35912", "35916", "35917", "35918", "35921", "35927", "35929", "35930", "35935", "35940", "35941", "35943", "35944", "35948", "35952", "35953", "35954", "35959", "35969", "35970", "35971", "35975", "35976", "35977", "35978", "35979", "35982", "35983", "35984", "35985", "35986", "35988", "35989", "35990", "35992", "35999", "36001", "36002", "36003", "36004", "36005", "36007", "36008", "36009", "36012", "36013", "36016", "36017", "36019", "36021", "36023", "36024", "36031", "36033", "36041", "36042", "36047", "36048", "36050", "36051", "36057", "36059", "36060", "36063", "36064", "36065", "36068", "36070", "36071", "36072", "36074", "36075", "36077", "36078", "36079", "36081", "36085", "36088", "36090", "36094", "36096", "36098", "36102", "36106", "36107", "36108", "36111", "36112", "36115", "36116", "36119", "36126", "36127", "36128", "36129", "36130", "36134", "36142", "36145", "36147", "36148", "36150", "36151", "36153", "36156", "36157", "36158", "36159", "36161", "36162", "36170", "36172", "36174", "36176", "36180", "36182", "36183", "36186", "36189", "36192", "36193", "36194", "36202", "36203", "36205", "36209", "36210", "36214", "36217", "36222", "36223", "36224", "36226", "36228", "36231", "36232", "36233", "36234", "36235", "36236", "36239", "36240", "36241", "36242", "36245", "36246", "36248", "36250", "36251", "36252", "36253", "36256", "36257", "36258", "36262", "36263", "36265", "36266", "36267", "36270", "36272", "36273", "36274", "36275", "36276", "36279", "36280", "36282", "36284", "36285", "36287", "36288", "36289", "36290", "36291", "36292", "36295", "36296", "36297", "36298", "36300", "36305", "36307", "36308", "36309", "36311", "36314", "36319", "36321", "36322", "36327", "36328", "36329", "36330", "36331", "36335", "36336", "36337", "36338", "36343", "36348", "36349", "36354", "36355", "36359", "36360", "36361", "36365", "36368", "36369", "36370", "36371", "36372", "36373", "36377", "36382", "36383", "36384", "36385", "36386", "36387", "36388", "36389", "36393", "36394", "36403", "36404", "36407", "36411", "36413", "36414", "36415", "36418", "36422", "36423", "36425", "36428", "36429", "36431", "36433", "36435", "36437", "36438", "36440", "36442", "36443", "36444", "36446", "36447", "36448", "36449", "36453", "36454", "36456", "36457", "36458", "36459", "36460", "36461", "36463", "36466", "36476", "36477", "36479", "36480", "36483", "36484", "36485", "36487", "36490", "36497", "36499", "36500", "36501", "36502", "36506", "36508", "36509", "36511", "36512", "36513", "36514", "36515", "36517", "36518", "36520", "36522", "36525", "36526", "36528", "36530", "36536", "36538", "36539", "36542", "36543", "36544", "36545", "36549", "36551", "36553", "36554", "36556", "36557", "36558", "36559", "36569", "36570", "36571", "36572", "36574", "36575", "36576", "36577", "36579", "36580", "36581", "36589", "36591", "36592", "36593", "36594", "36599", "36600", "36604", "36605", "36609", "36612", "36614", "36618", "36619", "36620", "36626", "36630", "36633", "36634", "36635", "36636", "36637", "36639", "36640", "36641", "36643", "36646", "36652", "36653", "36654", "36655", "36661", "36662", "36663", "36664", "36665", "36666", "36667", "36668", "36671", "36673", "36674", "36679", "36681", "36682", "36683", "36686", "36692", "36693", "36694", "36696", "36697", "36698", "36699", "36701", "36704", "36705", "36709", "36711", "36713", "36716", "36717", "36722", "36725", "36727", "36728", "36729", "36730", "36731", "36732", "36734", "36735", "36736", "36738", "36740", "36742", "36744", "36746", "36749", "36750", "36751", "36753", "36754", "36755", "36756", "36758", "36759", "36762", "36765", "36766", "36769", "36770", "36771", "36772", "36773", "36774", "36777", "36780", "36782", "36783", "36784", "36785", "36787", "36788", "36790", "36791", "36792", "36793", "36796", "36797", "36798", "36801", "36803", "36805", "36806", "36807", "36808", "36811", "36813", "36815", "36816", "36817", "36818", "36819", "36820", "36822", "36824", "36825", "36827", "36829", "36830", "36834", "36835", "36836", "36837", "36838", "36839", "36842", "36845", "36850", "36852", "36853", "36862", "36863", "36868", "36869", "36870", "36877", "36879", "36880", "36886", "36887", "36888", "36891", "36892", "36895", "36896", "36897", "36901", "36902", "36904", "36905", "36911", "36912", "36913", "36914", "36915", "36917", "36918", "36919", "36920", "36921", "36922", "36924", "36925", "36926", "36927", "36928", "36929", "36930", "36933", "36937", "36938", "36939", "36940", "36942", "36943", "36944", "36945", "36949", "36953", "36954", "36957", "36960", "36961", "36963", "36969", "36970", "36972", "36977", "36980", "36983", "36984", "36989", "36990", "36992", "36993", "36995", "36996", "36998", "36999", "37001", "37002", "37003", "37004", "37006", "37008", "37009", "37011", "37012", "37013", "37014", "37015", "37017", "37018", "37022", "37024", "37025", "37026", "37027", "37029", "37030", "37031", "37034", "37036", "37037", "37038", "37041", "37043", "37044", "37045", "37046", "37047", "37049", "37050", "37053", "37054", "37059", "37061", "37062", "37063", "37065", "37068", "37069", "37070", "37071", "37072", "37074", "37077", "37078", "37081", "37084", "37086", "37090", "37098", "37099", "37100", "37101", "37106", "37108", "37112", "37114", "37117", "37119", "37121", "37125", "37126", "37131", "37133", "37135", "37137", "37140", "37143", "37144", "37145", "37146", "37149", "37150", "37151", "37152", "37154", "37157", "37158", "37159", "37160", "37161", "37164", "37169", "37170", "37171", "37172", "37175", "37177", "37178", "37184", "37185", "37188", "37190", "37191", "37192", "37193", "37194", "37196", "37197", "37198", "37200", "37202", "37205", "37207", "37208", "37210", "37211", "37212", "37213", "37215", "37216", "37218", "37219", "37221", "37222", "37223", "37226", "37227", "37228", "37229", "37233", "37237", "37238", "37239", "37240", "37245", "37247", "37250", "37252", "37256", "37261", "37262", "37263", "37264", "37265", "37268", "37269", "37270", "37272", "37273", "37274", "37275", "37276", "37281", "37284", "37285", "37288", "37290", "37291", "37294", "37295", "37296", "37300", "37302", "37303", "37304", "37309", "37311", "37315", "37316", "37318", "37319", "37322", "37323", "37324", "37326", "37330", "37331", "37333", "37334", "37336", "37339", "37342", "37343", "37344", "37345", "37346", "37348", "37349", "37355", "37357", "37360", "37362", "37363", "37365", "37368", "37369", "37370", "37371", "37372", "37373", "37374", "37381", "37382", "37384", "37387", "37392", "37393", "37394", "37395", "37397", "37399", "37406", "37407", "37410", "37415", "37418", "37421", "37422", "37424", "37426", "37427", "37429", "37430", "37432", "37434", "37435", "37436", "37440", "37442", "37444", "37446", "37447", "37449", "37450", "37453", "37456", "37457", "37458", "37459", "37460", "37461", "37468", "37472", "37475", "37478", "37480", "37482", "37485", "37487", "37488", "37489", "37491", "37492", "37495", "37496", "37498", "37505", "37507", "37508", "37509", "37512", "37514", "37515", "37516", "37517", "37519", "37520", "37521", "37522", "37525", "37526", "37528", "37530", "37531", "37532", "37533", "37534", "37537", "37538", "37539", "37541", "37544", "37545", "37550", "37552", "37553", "37554", "37555", "37557", "37559", "37560", "37562", "37563", "37564", "37569", "37570", "37571", "37574", "37575", "37576", "37577", "37578", "37580", "37581", "37583", "37588", "37589", "37590", "37591", "37592", "37594", "37599", "37600", "37602", "37605", "37607", "37608", "37609", "37612", "37616", "37617", "37618", "37619", "37622", "37629", "37630", "37631", "37633", "37634", "37637", "37640", "37642", "37643", "37644", "37645", "37649", "37650", "37653", "37657", "37659", "37661", "37662", "37663", "37667", "37669", "37670", "37675", "37677", "37678", "37682", "37684", "37685", "37686", "37687", "37688", "37689", "37690", "37691", "37692", "37693", "37694", "37695", "37697", "37700", "37701", "37702", "37704", "37706", "37708", "37710", "37712", "37715", "37718", "37719", "37721", "37723", "37725", "37726", "37732", "37733", "37736", "37741", "37744", "37745", "37746", "37748", "37751", "37754", "37757", "37762", "37763", "37767", "37769", "37772", "37773", "37774", "37775", "37777", "37778", "37779", "37780", "37781", "37782", "37783", "37784", "37786", "37789", "37790", "37793", "37794", "37796", "37799", "37800", "37803", "37804", "37805", "37807", "37809", "37812", "37814", "37816", "37819", "37820", "37821", "37822", "37823", "37825", "37828", "37829", "37830", "37833", "37835", "37836", "37839", "37843", "37844", "37846", "37848", "37849", "37850", "37851", "37853", "37854", "37855", "37858", "37860", "37862", "37863", "37864", "37867", "37870", "37872", "37876", "37877", "37878", "37880", "37881", "37882", "37884", "37885", "37888", "37889", "37891", "37892", "37893", "37897", "37900", "37901", "37902", "37908", "37910", "37911", "37912", "37913", "37914", "37921", "37922", "37924", "37926", "37928", "37929", "37931", "37933", "37934", "37938", "37939", "37943", "37944", "37945", "37946", "37948", "37949", "37951", "37954", "37958", "37960", "37962", "37966", "37969", "37970", "37972", "37977", "37978", "37981", "37983", "37984", "37988", "37991", "37993", "37996", "37997", "37998", "37999", "38002", "38003", "38006", "38007", "38008", "38009", "38010", "38011", "38012", "38013", "38016", "38019", "38020", "38022", "38025", "38028", "38029", "38030", "38033", "38036", "38037", "38043", "38044", "38047", "38048", "38054", "38055", "38056", "38057", "38058", "38062", "38063", "38064", "38065", "38066", "38067", "38068", "38069", "38070", "38078", "38079", "38082", "38083", "38085", "38086", "38087", "38089", "38090", "38091", "38092", "38093", "38094", "38095", "38097", "38103", "38107", "38108", "38111", "38112", "38115", "38119", "38120", "38121", "38123", "38126", "38127", "38131", "38132", "38134", "38136", "38139", "38140", "38142", "38144", "38146", "38147", "38148", "38149", "38153", "38154", "38155", "38158", "38160", "38161", "38163", "38165", "38166", "38169", "38173", "38176", "38187", "38190", "38191", "38192", "38193", "38194", "38196", "38197", "38199", "38203", "38205", "38206", "38207", "38210", "38212", "38214", "38216", "38218", "38220", "38222", "38225", "38226", "38227", "38230", "38231", "38233", "38236", "38237", "38239", "38240", "38241", "38243", "38244", "38245", "38246", "38250", "38252", "38253", "38254", "38255", "38257", "38260", "38261", "38263", "38265", "38267", "38268", "38269", "38270", "38274", "38276", "38277", "38278", "38280", "38281", "38282", "38283", "38285", "38287", "38288", "38289", "38292", "38295", "38300", "38301", "38304", "38308", "38309", "38310", "38312", "38314", "38315", "38316", "38317", "38318", "38320", "38323", "38326", "38327", "38328", "38329", "38330", "38331", "38334", "38335", "38336", "38337", "38338", "38343", "38344", "38345", "38349", "38351", "38354", "38361", "38363", "38365", "38367", "38369", "38370", "38374", "38375", "38376", "38380", "38381", "38382", "38386", "38387", "38388", "38389", "38393", "38394", "38397", "38398", "38400", "38401", "38405", "38408", "38409", "38410", "38411", "38412", "38413", "38419", "38422", "38423", "38425", "38427", "38428", "38429", "38431", "38432", "38434", "38435", "38437", "38438", "38441", "38443", "38444", "38446", "38447", "38449", "38450", "38452", "38453", "38455", "38456", "38457", "38458", "38463", "38464", "38466", "38468", "38469", "38470", "38472", "38475", "38478", "38479", "38482", "38483", "38485", "38487", "38488", "38490", "38492", "38493", "38494", "38496", "38497", "38498", "38500", "38501", "38505", "38506", "38509", "38510", "38511", "38517", "38521", "38523", "38524", "38526", "38527", "38529", "38530", "38531", "38539", "38540", "38541", "38542", "38544", "38545", "38546", "38548", "38549", "38552", "38560", "38561", "38562", "38564", "38566", "38570", "38574", "38575", "38576", "38578", "38580", "38581", "38582", "38583", "38584", "38585", "38587", "38589", "38590", "38591", "38592", "38596", "38597", "38600", "38601", "38602", "38603", "38608", "38610", "38614", "38616", "38618", "38621", "38622", "38625", "38628", "38629", "38631", "38632", "38635", "38638", "38639", "38640", "38645", "38647", "38648", "38649", "38650", "38652", "38653", "38654", "38655", "38657", "38659", "38668", "38669", "38670", "38671", "38672", "38673", "38674", "38677", "38680", "38682", "38683", "38684", "38687", "38688", "38690", "38691", "38693", "38694", "38695", "38698", "38699", "38701", "38702", "38706", "38707", "38708", "38709", "38710", "38712", "38714", "38715", "38718", "38719", "38721", "38722", "38723", "38725", "38726", "38729", "38730", "38733", "38735", "38736", "38737", "38740", "38746", "38747", "38748", "38750", "38753", "38754", "38755", "38757", "38759", "38760", "38763", "38767", "38769", "38771", "38772", "38773", "38774", "38775", "38776", "38777", "38780", "38782", "38783", "38784", "38785", "38786", "38788", "38789", "38791", "38793", "38794", "38795", "38796", "38803", "38804", "38805", "38806", "38807", "38809", "38813", "38814", "38816", "38818", "38819", "38823", "38825", "38828", "38830", "38832", "38834", "38835", "38839", "38840", "38842", "38844", "38847", "38848", "38850", "38851", "38855", "38857", "38859", "38863", "38864", "38866", "38867", "38868", "38869", "38873", "38874", "38877", "38881", "38882", "38884", "38886", "38890", "38892", "38893", "38896", "38899", "38900", "38902", "38908", "38911", "38913", "38914", "38915", "38916", "38918", "38919", "38920", "38922", "38923", "38924", "38925", "38927", "38928", "38931", "38933", "38934", "38936", "38938", "38939", "38940", "38943", "38944", "38948", "38949", "38950", "38951", "38952", "38953", "38954", "38956", "38957", "38959", "38961", "38962", "38963", "38964", "38965", "38966", "38971", "38973", "38974", "38982", "38985", "38987", "38992", "38998", "38999", "39000", "39001", "39003", "39008", "39010", "39014", "39015", "39016", "39017", "39018", "39021", "39024", "39025", "39026", "39027", "39029", "39030", "39031", "39032", "39034", "39036", "39037", "39038", "39039", "39042", "39043", "39045", "39046", "39049", "39050", "39052", "39056", "39060", "39061", "39062", "39065", "39066", "39069", "39072", "39073", "39074", "39077", "39079", "39081", "39082", "39083", "39088", "39091", "39093", "39095", "39097", "39103", "39107", "39110", "39113", "39114", "39115", "39116", "39117", "39119", "39129", "39130", "39131", "39133", "39135", "39137", "39138", "39139", "39143", "39145", "39146", "39147", "39149", "39154", "39155", "39157", "39160", "39165", "39168", "39169", "39174", "39175", "39176", "39177", "39179", "39183", "39185", "39186", "39187", "39189", "39190", "39191", "39193", "39194", "39196", "39198", "39200", "39201", "39204", "39206", "39207", "39209", "39210", "39212", "39214", "39215", "39217", "39218", "39222", "39223", "39224", "39225", "39226", "39227", "39229", "39232", "39234", "39238", "39239", "39240", "39242", "39245", "39246", "39247", "39250", "39251", "39253", "39260", "39261", "39262", "39264", "39269", "39270", "39273", "39282", "39285", "39287", "39288", "39289", "39293", "39294", "39297", "39298", "39301", "39302", "39304", "39306", "39307", "39308", "39310", "39312", "39313", "39314", "39317", "39320", "39321", "39323", "39329", "39331", "39333", "39335", "39339", "39341", "39342", "39344", "39347", "39350", "39352", "39353", "39357", "39360", "39364", "39369", "39370", "39371", "39374", "39375", "39380", "39384", "39386", "39387", "39388", "39390", "39391", "39392", "39393", "39396", "39398", "39399", "39400", "39401", "39404", "39405", "39407", "39409", "39426", "39432", "39433", "39435", "39436", "39437", "39438", "39440", "39445", "39448", "39451", "39452", "39453", "39455", "39458", "39459", "39460", "39466", "39468", "39469", "39470", "39472", "39475", "39477", "39480", "39484", "39485", "39487", "39490", "39491", "39492", "39494", "39495", "39496", "39498", "39499", "39500", "39505", "39506", "39507", "39509", "39510", "39511", "39512", "39513", "39518", "39519", "39522", "39523", "39524", "39525", "39526", "39527", "39530", "39533", "39535", "39537", "39539", "39541", "39543", "39545", "39546", "39548", "39552", "39553", "39554", "39555", "39556", "39557", "39558", "39560", "39563", "39564", "39567", "39570", "39571", "39576", "39579", "39582", "39586", "39587", "39589", "39590", "39591", "39595", "39597", "39599", "39601", "39605", "39608", "39609", "39610", "39612", "39613", "39614", "39615", "39618", "39620", "39621", "39622", "39623", "39624", "39626", "39627", "39629", "39630", "39632", "39633", "39635", "39636", "39639", "39640", "39642", "39646", "39650", "39651", "39652", "39653", "39654", "39655", "39656", "39657", "39658", "39659", "39661", "39662", "39663", "39664", "39668", "39669", "39671", "39673", "39674", "39675", "39676", "39677", "39678", "39684", "39685", "39686", "39688", "39689", "39690", "39694", "39699", "39702", "39703", "39704", "39705", "39707", "39708", "39712", "39713", "39714", "39719", "39720", "39722", "39723", "39725", "39726", "39727", "39728", "39729", "39732", "39734", "39735", "39736", "39737", "39738", "39739", "39740", "39741", "39744", "39746", "39747", "39753", "39754", "39755", "39758", "39760", "39761", "39762", "39763", "39765", "39766", "39768", "39769", "39771", "39773", "39774", "39775", "39776", "39777", "39778", "39784", "39785", "39786", "39787", "39788", "39792", "39794", "39797", "39801", "39802", "39805", "39806", "39808", "39809", "39810", "39811", "39812", "39816", "39818", "39819", "39820", "39821", "39822", "39825", "39828", "39829", "39830", "39831", "39833", "39834", "39836", "39841", "39842", "39843", "39858", "39860", "39861", "39863", "39867", "39868", "39869", "39871", "39872", "39873", "39875", "39876", "39879", "39880", "39883", "39885", "39887", "39889", "39893", "39896", "39897", "39898", "39900", "39903", "39905", "39906", "39908", "39910", "39913", "39914", "39916", "39918", "39920", "39923", "39926", "39928", "39930", "39934", "39935", "39941", "39942", "39947", "39948", "39952", "39953", "39954", "39955", "39957", "39958", "39961", "39967", "39969", "39971", "39972", "39973", "39977", "39983", "39985", "39986", "39987", "39988", "39989", "39991", "39992", "39993", "39995", "39998", "39999", "40001", "40005", "40006", "40007", "40008", "40009", "40010", "40011", "40013", "40014", "40015", "40016", "40021", "40024", "40027", "40030", "40031", "40032", "40033", "40034", "40035", "40037", "40040", "40045", "40046", "40048", "40050", "40051", "40052", "40053", "40054", "40058", "40060", "40061", "40064", "40065", "40066", "40067", "40068", "40071", "40072", "40073", "40075", "40081", "40083", "40086", "40090", "40093", "40095", "40096", "40098", "40099", "40103", "40106", "40107", "40110", "40112", "40113", "40115", "40116", "40118", "40119", "40122", "40123", "40124", "40126", "40129", "40135", "40136", "40137", "40138", "40139", "40143", "40146", "40147", "40150", "40151", "40152", "40153", "40154", "40157", "40158", "40159", "40162", "40164", "40165", "40166", "40167", "40168", "40169", "40170", "40175", "40176", "40177", "40179", "40180", "40181", "40183", "40184", "40185", "40187", "40189", "40190", "40191", "40192", "40193", "40199", "40201", "40204", "40207", "40211", "40215", "40220", "40223", "40224", "40226", "40227", "40228", "40230", "40231", "40232", "40234", "40235", "40237", "40239", "40242", "40243", "40244", "40245", "40247", "40248", "40252", "40253", "40254", "40255", "40256", "40258", "40259", "40262", "40263", "40265", "40268", "40269", "40273", "40275", "40276", "40277", "40278", "40281", "40283", "40284", "40287", "40288", "40290", "40291", "40292", "40294", "40296", "40298", "40299", "40304", "40306", "40307", "40309", "40310", "40312", "40313", "40318", "40319", "40320", "40321", "40324", "40331", "40339", "40341", "40342", "40344", "40348", "40350", "40351", "40352", "40356", "40357", "40359", "40362", "40363", "40364", "40366", "40368", "40371", "40372", "40373", "40374", "40375", "40376", "40378", "40379", "40381", "40383", "40384", "40390", "40392", "40394", "40396", "40397", "40399", "40400", "40401", "40402", "40404", "40407", "40408", "40409", "40412", "40414", "40418", "40419", "40421", "40422", "40423", "40424", "40426", "40431", "40433", "40434", "40435", "40438", "40440", "40442", "40444", "40449", "40450", "40451", "40452", "40453", "40454", "40455", "40458", "40459", "40460", "40466", "40467", "40474", "40475", "40478", "40480", "40485", "40486", "40489", "40490", "40493", "40494", "40495", "40496", "40497", "40499", "40500", "40503", "40506", "40507", "40508", "40509", "40510", "40511", "40512", "40513", "40515", "40516", "40518", "40519", "40521", "40523", "40524", "40527", "40528", "40529", "40530", "40531", "40532", "40533", "40536", "40537", "40538", "40542", "40546", "40549", "40550", "40553", "40555", "40556", "40558", "40560", "40566", "40567", "40568", "40576", "40578", "40581", "40582", "40583", "40586", "40587", "40590", "40591", "40592", "40595", "40596", "40597", "40598", "40599", "40600", "40602", "40605", "40609", "40610", "40611", "40612", "40613", "40615", "40616", "40617", "40619", "40622", "40623", "40624", "40630", "40637", "40642", "40643", "40644", "40646", "40648", "40651", "40652", "40655", "40656", "40659", "40660", "40661", "40662", "40663", "40664", "40665", "40671", "40672", "40673", "40675", "40676", "40678", "40680", "40681", "40682", "40684", "40685", "40687", "40688", "40689", "40693", "40694", "40695", "40698", "40704", "40705", "40709", "40711", "40713", "40718", "40721", "40722", "40723", "40724", "40725", "40727", "40731", "40732", "40733", "40734", "40735", "40736", "40738", "40739", "40741", "40742", "40745", "40746", "40748", "40751", "40752", "40753", "40760", "40763", "40764", "40766", "40768", "40769", "40774", "40775", "40776", "40777", "40779", "40780", "40782", "40784", "40786", "40787", "40788", "40790", "40792", "40793", "40797", "40798", "40800", "40801", "40802", "40803", "40804", "40806", "40807", "40810", "40813", "40814", "40816", "40818", "40820", "40821", "40824", "40826", "40827", "40829", "40836", "40839", "40841", "40845", "40850", "40851", "40852", "40853", "40854", "40858", "40859", "40861", "40862", "40863", "40864", "40866", "40867", "40869", "40870", "40872", "40873", "40876", "40877", "40878", "40879", "40880", "40881", "40882", "40883", "40884", "40886", "40888", "40889", "40895", "40896", "40897", "40901", "40903", "40906", "40908", "40910", "40913", "40914", "40924", "40925", "40926", "40928", "40932", "40933", "40935", "40937", "40938", "40939", "40941", "40945", "40949", "40950", "40951", "40952", "40953", "40957", "40958", "40959", "40963", "40964", "40966", "40969", "40970", "40971", "40972", "40973", "40974", "40979", "40984", "40986", "40987", "40988", "40989", "40990", "40993", "40995", "40996", "40997", "40998", "40999", "41003", "41005", "41006", "41007", "41012", "41015", "41016", "41017", "41018", "41020", "41022", "41029", "41032", "41033", "41034", "41035", "41036", "41037", "41040", "41044", "41046", "41047", "41050", "41055", "41056", "41057", "41058", "41060", "41061", "41063", "41067", "41069", "41072", "41074", "41077", "41079", "41083", "41085", "41087", "41088", "41091", "41093", "41094", "41095", "41100", "41104", "41105", "41107", "41108", "41109", "41111", "41114", "41116", "41117", "41118", "41119", "41122", "41124", "41125", "41126", "41129", "41130", "41131", "41133", "41134", "41135", "41137", "41140", "41141", "41142", "41143", "41145", "41147", "41148", "41149", "41151", "41152", "41153", "41156", "41159", "41162", "41164", "41165", "41166", "41167", "41170", "41171", "41173", "41177", "41178", "41179", "41180", "41181", "41184", "41190", "41191", "41193", "41194", "41195", "41198", "41201", "41203", "41206", "41211", "41215", "41217", "41218", "41220", "41224", "41225", "41226", "41230", "41231", "41232", "41233", "41234", "41236", "41239", "41240", "41241", "41250", "41253", "41255", "41256", "41258", "41259", "41260", "41263", "41266", "41267", "41270", "41271", "41272", "41274", "41275", "41279", "41280", "41281", "41283", "41284", "41285", "41288", "41289", "41293", "41294", "41295", "41300", "41305", "41306", "41307", "41308", "41311", "41313", "41314", "41315", "41316", "41317", "41318", "41319", "41320", "41324", "41325", "41329", "41334", "41335", "41338", "41340", "41342", "41343", "41345", "41347", "41349", "41350", "41352", "41353", "41355", "41356", "41357", "41358", "41359", "41362", "41363", "41364", "41365", "41367", "41368", "41369", "41370", "41371", "41372", "41375", "41376", "41377", "41381", "41383", "41384", "41386", "41388", "41389", "41393", "41394", "41395", "41396", "41397", "41398", "41400", "41401", "41402", "41405", "41409", "41410", "41412", "41418", "41419", "41421", "41423", "41425", "41426", "41428", "41434", "41437", "41440", "41442", "41444", "41445", "41447", "41449", "41451", "41452", "41454", "41456", "41459", "41461", "41464", "41470", "41474", "41475", "41476", "41478", "41480", "41481", "41483", "41484", "41487", "41490", "41491", "41492", "41493", "41494", "41495", "41496", "41497", "41498", "41499", "41500", "41501", "41502", "41505", "41506", "41509", "41510", "41511", "41513", "41515", "41518", "41519", "41521", "41524", "41526", "41528", "41532", "41534", "41535", "41537", "41539", "41541", "41544", "41545", "41547", "41548", "41549", "41551", "41553", "41554", "41555", "41556", "41557", "41558", "41562", "41565", "41566", "41567", "41568", "41570", "41571", "41573", "41574", "41575", "41577", "41578", "41580", "41581", "41583", "41586", "41587", "41588", "41590", "41591", "41592", "41594", "41598", "41600", "41602", "41604", "41605", "41606", "41610", "41611", "41613", "41618", "41620", "41622", "41624", "41630", "41632", "41635", "41638", "41640", "41642", "41643", "41648", "41650", "41651", "41656", "41657", "41658", "41660", "41663", "41665", "41666", "41667", "41672", "41674", "41676", "41678", "41681", "41683", "41684", "41686", "41687", "41689", "41691", "41695", "41696", "41699", "41701", "41703", "41706", "41711", "41712", "41713", "41714", "41716", "41723", "41726", "41727", "41728", "41729", "41733", "41734", "41736", "41739", "41741", "41743", "41744", "41745", "41746", "41748", "41755", "41756", "41757", "41761", "41763", "41765", "41767", "41770", "41773", "41774", "41777", "41778", "41779", "41780", "41785", "41786", "41787", "41788", "41791", "41792", "41794", "41797", "41800", "41803", "41804", "41807", "41810", "41812", "41813", "41814", "41815", "41816", "41817", "41818", "41819", "41820", "41822", "41826", "41828", "41830", "41833", "41834", "41835", "41838", "41839", "41844", "41846", "41847", "41849", "41854", "41855", "41856", "41857", "41859", "41861", "41862", "41863", "41865", "41868", "41869", "41870", "41871", "41874", "41878", "41880", "41881", "41882", "41883", "41884", "41886", "41887", "41888", "41890", "41892", "41896", "41897", "41899", "41907", "41909", "41913", "41914", "41916", "41918", "41919", "41920", "41921", "41922", "41927", "41928", "41931", "41932", "41934", "41936", "41937", "41938", "41940", "41943", "41944", "41947", "41948", "41949", "41954", "41955", "41956", "41957", "41961", "41962", "41963", "41964", "41967", "41968", "41969", "41970", "41972", "41973", "41975", "41977", "41978", "41979", "41980", "41981", "41982", "41983", "41984", "41985", "41986", "41987", "41989", "41993", "41994", "41995", "41996", "41998", "41999", "42003", "42004", "42005", "42006", "42010", "42011", "42013", "42016", "42017", "42019", "42020", "42021", "42025", "42027", "42028", "42031", "42032", "42034", "42038", "42041", "42043", "42044", "42045", "42050", "42051", "42053", "42054", "42055", "42056", "42057", "42059", "42061", "42063", "42064", "42067", "42068", "42069", "42070", "42072", "42074", "42075", "42077", "42078", "42081", "42083", "42085", "42086", "42089", "42092", "42093", "42096", "42098", "42099", "42101", "42105", "42107", "42109", "42111", "42114", "42115", "42116", "42117", "42118", "42124", "42126", "42127", "42128", "42129", "42131", "42132", "42137", "42139", "42140", "42141", "42144", "42145", "42152", "42153", "42154", "42155", "42159", "42161", "42163", "42164", "42166", "42167", "42169", "42171", "42172", "42173", "42175", "42178", "42180", "42181", "42191", "42193", "42196", "42197", "42198", "42202", "42204", "42207", "42209", "42210", "42211", "42213", "42219", "42220", "42225", "42226", "42227", "42229", "42232", "42235", "42237", "42243", "42246", "42248", "42254", "42256", "42258", "42259", "42260", "42262", "42263", "42265", "42266", "42267", "42268", "42270", "42274", "42275", "42276", "42278", "42280", "42283", "42284", "42285", "42286", "42292", "42293", "42296", "42297", "42301", "42310", "42313", "42314", "42315", "42316", "42318", "42322", "42323", "42324", "42325", "42326", "42328", "42330", "42331", "42334", "42335", "42337", "42339", "42340", "42341", "42342", "42343", "42344", "42345", "42346", "42347", "42348", "42349", "42352", "42354", "42355", "42357", "42358", "42360", "42361", "42362", "42364", "42366", "42367", "42368", "42372", "42373", "42375", "42376", "42377", "42378", "42380", "42381", "42382", "42383", "42384", "42391", "42394", "42398", "42399", "42401", "42403", "42407", "42409", "42410", "42411", "42413", "42414", "42415", "42416", "42417", "42418", "42420", "42421", "42422", "42424", "42428", "42430", "42432", "42434", "42435", "42436", "42437", "42438", "42441", "42444", "42446", "42447", "42453", "42454", "42456", "42459", "42460", "42461", "42465", "42466", "42470", "42472", "42475", "42476", "42481", "42483", "42484", "42486", "42487", "42489", "42490", "42491", "42495", "42497", "42499", "42500", "42501", "42504", "42505", "42509", "42510", "42516", "42517", "42519", "42520", "42522", "42523", "42524", "42525", "42526", "42527", "42528", "42533", "42534", "42535", "42536", "42538", "42542", "42545", "42547", "42548", "42550", "42551", "42554", "42555", "42557", "42558", "42560", "42561", "42564", "42565", "42567", "42569", "42571", "42572", "42573", "42576", "42577", "42580", "42582", "42584", "42587", "42590", "42593", "42594", "42596", "42598", "42599", "42602", "42606", "42609", "42612", "42615", "42618", "42621", "42622", "42623", "42624", "42625", "42626", "42635", "42637", "42641", "42643", "42645", "42648", "42651", "42655", "42656", "42659", "42660", "42666", "42667", "42669", "42670", "42671", "42672", "42673", "42674", "42675", "42676", "42678", "42680", "42681", "42682", "42686", "42687", "42690", "42692", "42693", "42697", "42698", "42699", "42700", "42705", "42706", "42707", "42711", "42712", "42713", "42714", "42716", "42717", "42718", "42719", "42721", "42723", "42724", "42727", "42728", "42729", "42731", "42733", "42734", "42738", "42741", "42745", "42749", "42750", "42752", "42757", "42759", "42760", "42764", "42765", "42769", "42771", "42772", "42773", "42774", "42776", "42781", "42782", "42783", "42784", "42786", "42788", "42789", "42791", "42792", "42793", "42794", "42797", "42798", "42802", "42806", "42807", "42808", "42810", "42811", "42814", "42817", "42821", "42822", "42824", "42825", "42826", "42828", "42829", "42830", "42831", "42832", "42833", "42834", "42835", "42836", "42840", "42841", "42842", "42844", "42845", "42849", "42850", "42851", "42852", "42853", "42854", "42855", "42856", "42857", "42858", "42859", "42862", "42863", "42865", "42867", "42868", "42870", "42872", "42875", "42876", "42877", "42878", "42880", "42882", "42884", "42885", "42887", "42889", "42890", "42892", "42894", "42897", "42900", "42903", "42904", "42905", "42907", "42908", "42909", "42913", "42914", "42916", "42919", "42920", "42922", "42925", "42926", "42929", "42933", "42934", "42935", "42936", "42937", "42938", "42947", "42948", "42951", "42956", "42957", "42961", "42962", "42963", "42965", "42967", "42968", "42973", "42974", "42975", "42977", "42980", "42982", "42983", "42984", "42985", "42987", "42988", "42989", "42990", "42995", "42996", "42999", "43001", "43002", "43003", "43006", "43013", "43019", "43022", "43023", "43027", "43029", "43032", "43038", "43039", "43041", "43042", "43047", "43048", "43051", "43054", "43055", "43060", "43061", "43062", "43064", "43065", "43067", "43068", "43069", "43070", "43071", "43072", "43077", "43079", "43080", "43081", "43085", "43086", "43087", "43088", "43089", "43094", "43100", "43101", "43102", "43107", "43108", "43113", "43114", "43117", "43118", "43121", "43122", "43124", "43125", "43127", "43129", "43130", "43132", "43133", "43134", "43135", "43138", "43141", "43142", "43146", "43147", "43150", "43152", "43156", "43157", "43160", "43167", "43170", "43172", "43175", "43178", "43179", "43180", "43181", "43182", "43183", "43184", "43185", "43187", "43190", "43192", "43194", "43196", "43198", "43199", "43200", "43202", "43205", "43207", "43208", "43209", "43211", "43214", "43216", "43219", "43223", "43226", "43227", "43228", "43229", "43230", "43233", "43234", "43235", "43237", "43238", "43239", "43240", "43241", "43244", "43245", "43246", "43247", "43249", "43250", "43252", "43254", "43256", "43257", "43260", "43261", "43262", "43263", "43265", "43266", "43267", "43268", "43269", "43270", "43271", "43272", "43274", "43275", "43276", "43279", "43281", "43284", "43286", "43287", "43289", "43291", "43295", "43296", "43297", "43299", "43303", "43306", "43308", "43309", "43312", "43314", "43315", "43318", "43321", "43324", "43325", "43330", "43331", "43332", "43334", "43335", "43338", "43339", "43340", "43341", "43344", "43345", "43346", "43347", "43348", "43349", "43350", "43351", "43355", "43356", "43357", "43358", "43360", "43365", "43366", "43367", "43368", "43370", "43371", "43373", "43374", "43378", "43379", "43382", "43386", "43389", "43390", "43392", "43397", "43401", "43402", "43408", "43409", "43410", "43411", "43412", "43415", "43419", "43420", "43422", "43423", "43426", "43427", "43430", "43431", "43432", "43433", "43437", "43439", "43441", "43442", "43443", "43446", "43447", "43448", "43450", "43453", "43454", "43456", "43458", "43459", "43460", "43461", "43462", "43465", "43467", "43469", "43471", "43473", "43474", "43476", "43481", "43483", "43484", "43485", "43486", "43490", "43495", "43498", "43500", "43501", "43502", "43508", "43509", "43510", "43520", "43521", "43524", "43525", "43526", "43527", "43528", "43532", "43533", "43534", "43540", "43542", "43543", "43544", "43548", "43549", "43555", "43556", "43558", "43559", "43563", "43566", "43567", "43570", "43571", "43575", "43576", "43580", "43581", "43583", "43584", "43586", "43587", "43588", "43589", "43590", "43592", "43594", "43595", "43596", "43598", "43599", "43600", "43601", "43605", "43606", "43607", "43610", "43612", "43614", "43616", "43617", "43622", "43623", "43625", "43626", "43627", "43630", "43631", "43632", "43636", "43638", "43642", "43643", "43644", "43645", "43647", "43650", "43651", "43653", "43658", "43659", "43663", "43665", "43666", "43667", "43669", "43670", "43677", "43678", "43679", "43680", "43683", "43685", "43689", "43691", "43692", "43693", "43694", "43697", "43698", "43699", "43703", "43708", "43711", "43716", "43718", "43720", "43722", "43723", "43724", "43725", "43726", "43730", "43731", "43734", "43739", "43741", "43742", "43744", "43747", "43748", "43749", "43751", "43752", "43760", "43763", "43764", "43768", "43770", "43776", "43780", "43782", "43783", "43787", "43788", "43789", "43791", "43793", "43795", "43796", "43798", "43799", "43804", "43805", "43808", "43809", "43815", "43816", "43817", "43818", "43819", "43820", "43821", "43822", "43823", "43825", "43826", "43828", "43830", "43833", "43834", "43838", "43842", "43843", "43844", "43847", "43848", "43850", "43851", "43857", "43860", "43861", "43863", "43866", "43867", "43868", "43869", "43870", "43872", "43873", "43874", "43875", "43877", "43878", "43879", "43880", "43881", "43882", "43883", "43884", "43886", "43887", "43888", "43892", "43898", "43899", "43903", "43907", "43908", "43912", "43914", "43916", "43917", "43918", "43921", "43922", "43923", "43925", "43931", "43932", "43934", "43936", "43939", "43944", "43946", "43948", "43951", "43952", "43956", "43957", "43959", "43960", "43963", "43966", "43968", "43969", "43970", "43971", "43972", "43975", "43976", "43978", "43979", "43982", "43983", "43984", "43985", "43986", "43989", "43990", "43993", "43994", "43997", "43998", "44001", "44003", "44005", "44007", "44008", "44009", "44010", "44012", "44013", "44016", "44018", "44019", "44023", "44025", "44026", "44027", "44029", "44030", "44031", "44032", "44034", "44035", "44036", "44038", "44040", "44041", "44042", "44044", "44046", "44048", "44050", "44051", "44053", "44054", "44055", "44057", "44059", "44060", "44062", "44068", "44069", "44071", "44073", "44074", "44075", "44076", "44080", "44081", "44084", "44085", "44086", "44090", "44091", "44092", "44094", "44097", "44098", "44099", "44100", "44101", "44102", "44104", "44106", "44107", "44108", "44110", "44112", "44115", "44116", "44118", "44119", "44120", "44121", "44123", "44124", "44125", "44126", "44127", "44128", "44129", "44131", "44133", "44136", "44137", "44138", "44142", "44144", "44145", "44146", "44147", "44148", "44149", "44150", "44153", "44156", "44157", "44161", "44162", "44164", "44165", "44166", "44171", "44174", "44178", "44180", "44181", "44182", "44183", "44184", "44185", "44187", "44188", "44189", "44192", "44193", "44196", "44197", "44200", "44201", "44203", "44204", "44207", "44210", "44212", "44214", "44215", "44221", "44225", "44228", "44232", "44233", "44235", "44236", "44237", "44238", "44239", "44240", "44241", "44242", "44246", "44247", "44248", "44249", "44250", "44251", "44253", "44256", "44261", "44263", "44268", "44269", "44270", "44273", "44274", "44275", "44278", "44282", "44284", "44286", "44288", "44292", "44293", "44295", "44296", "44297", "44298", "44304", "44305", "44306", "44308", "44309", "44311", "44313", "44314", "44318", "44319", "44321", "44323", "44326", "44328", "44329", "44330", "44334", "44335", "44337", "44340", "44341", "44342", "44345", "44346", "44347", "44348", "44351", "44353", "44356", "44358", "44359", "44360", "44361", "44362", "44364", "44365", "44367", "44369", "44371", "44372", "44373", "44374", "44376", "44377", "44379", "44380", "44385", "44389", "44390", "44395", "44396", "44398", "44401", "44403", "44404", "44407", "44408", "44409", "44410", "44411", "44412", "44413", "44415", "44416", "44418", "44420", "44421", "44424", "44425", "44428", "44429", "44430", "44432", "44433", "44435", "44436", "44440", "44441", "44443", "44444", "44446", "44447", "44448", "44449", "44451", "44455", "44457", "44458", "44459", "44460", "44462", "44463", "44464", "44467", "44469", "44472", "44474", "44475", "44478", "44481", "44482", "44484", "44485", "44486", "44490", "44491", "44496", "44497", "44498", "44499", "44502", "44503", "44504", "44505", "44507", "44515", "44517", "44522", "44523", "44525", "44531", "44534", "44539", "44541", "44544", "44547", "44548", "44550", "44556", "44560", "44561", "44564", "44565", "44566", "44571", "44572", "44576", "44579", "44582", "44584", "44585", "44587", "44588", "44589", "44591", "44594", "44595", "44598", "44602", "44604", "44608", "44609", "44616", "44619", "44620", "44623", "44624", "44627", "44628", "44633", "44634", "44636", "44637", "44639", "44641", "44645", "44651", "44654", "44657", "44660", "44661", "44662", "44667", "44669", "44670", "44672", "44674", "44675", "44677", "44678", "44679", "44680", "44685", "44689", "44690", "44692", "44693", "44694", "44696", "44697", "44699", "44700", "44702", "44703", "44704", "44706", "44707", "44708", "44710", "44711", "44712", "44713", "44715", "44716", "44719", "44720", "44721", "44724", "44726", "44727", "44731", "44733", "44736", "44738", "44739", "44740", "44742", "44743", "44744", "44746", "44748", "44749", "44750", "44751", "44759", "44760", "44762", "44763", "44764", "44768", "44770", "44771", "44775", "44776", "44778", "44779", "44781", "44782", "44784", "44785", "44786", "44787", "44788", "44790", "44791", "44796", "44799", "44802", "44803", "44804", "44805", "44806", "44808", "44810", "44813", "44816", "44817", "44818", "44823", "44831", "44832", "44834", "44835", "44839", "44840", "44841", "44844", "44849", "44850", "44851", "44852", "44853", "44854", "44855", "44857", "44860", "44863", "44864", "44867", "44868", "44874", "44876", "44877", "44884", "44885", "44886", "44887", "44888", "44890", "44891", "44893", "44894", "44899", "44900", "44904", "44905", "44907", "44908", "44909", "44915", "44916", "44917", "44918", "44919", "44921", "44923", "44924", "44925", "44926", "44930", "44932", "44933", "44934", "44936", "44937", "44940", "44941", "44943", "44944", "44945", "44949", "44952", "44957", "44959", "44963", "44965", "44966", "44967", "44968", "44969", "44970", "44971", "44979", "44980", "44981", "44982", "44983", "44984", "44985", "44987", "44989", "44990", "44992", "44997", "45000", "45001", "45003", "45006", "45012", "45014", "45015", "45016", "45022", "45024", "45025", "45029", "45031", "45032", "45033", "45035", "45037", "45038", "45043", "45044", "45046", "45048", "45049", "45050", "45052", "45053", "45054", "45061", "45062", "45063", "45064", "45065", "45067", "45068", "45070", "45071", "45073", "45074", "45077", "45078", "45082", "45083", "45084", "45085", "45086", "45089", "45091", "45092", "45094", "45096", "45099", "45101", "45102", "45103", "45105", "45106", "45107", "45108", "45115", "45116", "45118", "45120", "45121", "45123", "45124", "45125", "45126", "45128", "45134", "45136", "45137", "45139", "45140", "45142", "45145", "45146", "45147", "45149", "45150", "45154", "45155", "45156", "45157", "45158", "45160", "45162", "45164", "45165", "45168", "45169", "45171", "45173", "45176", "45178", "45179", "45180", "45181", "45182", "45186", "45187", "45189", "45190", "45197", "45198", "45201", "45202", "45205", "45211", "45217", "45220", "45223", "45224", "45227", "45229", "45230", "45231", "45233", "45235", "45236", "45237", "45239", "45240", "45241", "45243", "45244", "45245", "45246", "45248", "45249", "45251", "45252", "45254", "45258", "45260", "45267", "45268", "45269", "45274", "45275", "45276", "45278", "45282", "45283", "45284", "45285", "45286", "45288", "45290", "45291", "45295", "45296", "45298", "45299", "45300", "45301", "45302", "45304", "45305", "45309", "45311", "45312", "45313", "45320", "45324", "45326", "45327", "45328", "45329", "45333", "45334", "45335", "45336", "45337", "45338", "45339", "45340", "45342", "45347", "45349", "45352", "45353", "45354", "45355", "45358", "45362", "45363", "45368", "45370", "45372", "45373", "45374", "45375", "45378", "45379", "45380", "45382", "45383", "45387", "45388", "45391", "45393", "45396", "45397", "45399", "45402", "45403", "45406", "45407", "45408", "45409", "45412", "45413", "45414", "45415", "45418", "45421", "45422", "45423", "45427", "45429", "45430", "45431", "45432", "45434", "45438", "45439", "45440", "45442", "45445", "45446", "45449", "45450", "45452", "45455", "45456", "45457", "45458", "45460", "45461", "45463", "45464", "45467", "45469", "45470", "45471", "45472", "45478", "45479", "45483", "45487", "45490", "45492", "45493", "45494", "45496", "45499", "45501", "45505", "45506", "45509", "45514", "45515", "45517", "45518", "45520", "45521", "45522", "45523", "45524", "45526", "45529", "45530", "45532", "45533", "45535", "45536", "45539", "45542", "45544", "45546", "45547", "45551", "45555", "45559", "45562", "45564", "45565", "45566", "45567", "45568", "45569", "45572", "45575", "45579", "45580", "45581", "45584", "45586", "45587", "45588", "45589", "45593", "45594", "45595", "45596", "45598", "45599", "45602", "45604", "45607", "45609", "45612", "45613", "45614", "45615", "45616", "45617", "45620", "45621", "45622", "45623", "45625", "45626", "45629", "45630", "45631", "45632", "45633", "45638", "45639", "45640", "45642", "45643", "45644", "45645", "45646", "45647", "45648", "45649", "45652", "45653", "45654", "45655", "45656", "45657", "45661", "45662", "45663", "45664", "45665", "45666", "45674", "45675", "45676", "45677", "45679", "45680", "45684", "45685", "45687", "45689", "45690", "45691", "45692", "45694", "45695", "45697", "45699", "45700", "45701", "45704", "45705", "45707", "45709", "45710", "45712", "45714", "45715", "45717", "45718", "45719", "45720", "45722", "45723", "45724", "45726", "45727", "45728", "45731", "45732", "45735", "45736", "45741", "45743", "45744", "45749", "45752", "45753", "45754", "45756", "45760", "45768", "45770", "45771", "45772", "45776", "45777", "45778", "45779", "45781", "45783", "45784", "45787", "45792", "45801", "45806", "45807", "45808", "45809", "45812", "45813", "45816", "45819", "45820", "45824", "45825", "45830", "45831", "45833", "45834", "45835", "45836", "45838", "45841", "45845", "45846", "45848", "45849", "45855", "45856", "45860", "45863", "45866", "45867", "45868", "45869", "45871", "45872", "45874", "45875", "45876", "45877", "45879", "45880", "45883", "45885", "45886", "45887", "45889", "45890", "45893", "45894", "45898", "45900", "45901", "45906", "45909", "45913", "45915", "45919", "45920", "45922", "45924", "45925", "45926", "45928", "45934", "45935", "45937", "45940", "45942", "45943", "45944", "45945", "45946", "45947", "45949", "45951", "45952", "45957", "45959", "45961", "45964", "45965", "45968", "45970", "45976", "45977", "45978", "45980", "45981", "45982", "45983", "45985", "45986", "45988", "45992", "45993", "46003", "46004", "46005", "46012", "46014", "46017", "46018", "46019", "46021", "46022", "46023", "46029", "46032", "46033", "46036", "46037", "46041", "46043", "46047", "46048", "46051", "46052", "46055", "46057", "46058", "46059", "46062", "46063", "46068", "46069", "46071", "46072", "46074", "46075", "46080", "46081", "46084", "46085", "46089", "46091", "46095", "46096", "46097", "46098", "46099", "46100", "46103", "46104", "46105", "46107", "46109", "46111", "46112", "46113", "46115", "46119", "46121", "46122", "46123", "46124", "46127", "46129", "46130", "46131", "46133", "46134", "46135", "46136", "46137", "46138", "46139", "46141", "46144", "46146", "46147", "46149", "46150", "46154", "46155", "46158", "46159", "46164", "46165", "46171", "46172", "46173", "46174", "46177", "46178", "46185", "46186", "46188", "46189", "46190", "46191", "46194", "46199", "46200", "46206", "46209", "46212", "46214", "46215", "46216", "46219", "46222", "46223", "46224", "46225", "46231", "46233", "46235", "46236", "46243", "46246", "46248", "46249", "46257", "46259", "46264", "46265", "46267", "46268", "46269", "46272", "46273", "46278", "46279", "46280", "46281", "46282", "46283", "46284", "46286", "46288", "46290", "46295", "46296", "46297", "46298", "46300", "46301", "46303", "46307", "46308", "46310", "46311", "46313", "46316", "46321", "46328", "46331", "46332", "46333", "46336", "46337", "46338", "46339", "46341", "46342", "46344", "46348", "46349", "46350", "46351", "46352", "46353", "46355", "46356", "46359", "46360", "46361", "46362", "46364", "46366", "46370", "46371", "46372", "46376", "46378", "46379", "46380", "46385", "46386", "46390", "46391", "46395", "46398", "46399", "46401", "46402", "46403", "46404", "46406", "46407", "46411", "46413", "46414", "46415", "46421", "46422", "46423", "46424", "46426", "46427", "46428", "46432", "46437", "46438", "46439", "46440", "46441", "46442", "46443", "46444", "46446", "46447", "46448", "46450", "46452", "46455", "46456", "46459", "46461", "46462", "46463", "46464", "46467", "46471", "46472", "46474", "46475", "46476", "46477", "46478", "46480", "46484", "46485", "46486", "46490", "46491", "46494", "46495", "46503", "46505", "46507", "46508", "46510", "46511", "46512", "46517", "46519", "46520", "46522", "46524", "46526", "46527", "46528", "46531", "46532", "46534", "46537", "46541", "46542", "46543", "46545", "46546", "46549", "46553", "46560", "46562", "46564", "46567", "46568", "46569", "46570", "46571", "46572", "46573", "46574", "46580", "46585", "46587", "46588", "46589", "46591", "46592", "46601", "46603", "46605", "46606", "46607", "46609", "46610", "46611", "46616", "46617", "46621", "46622", "46623", "46625", "46627", "46632", "46633", "46639", "46640", "46641", "46642", "46646", "46648", "46649", "46650", "46652", "46653", "46655", "46657", "46658", "46659", "46661", "46665", "46666", "46667", "46668", "46669", "46670", "46671", "46679", "46680", "46681", "46683", "46684", "46685", "46686", "46687", "46688", "46689", "46694", "46699", "46702", "46704", "46705", "46707", "46710", "46711", "46713", "46716", "46719", "46721", "46722", "46723", "46725", "46726", "46729", "46734", "46735", "46736", "46740", "46741", "46744", "46746", "46747", "46749", "46751", "46754", "46759", "46761", "46762", "46764", "46765", "46766", "46767", "46768", "46769", "46772", "46773", "46774", "46775", "46777", "46781", "46784", "46785", "46786", "46788", "46789", "46791", "46793", "46794", "46795", "46797", "46798", "46802", "46806", "46810", "46812", "46814", "46816", "46820", "46824", "46827", "46828", "46830", "46833", "46835", "46837", "46838", "46841", "46842", "46848", "46850", "46851", "46852", "46853", "46854", "46855", "46857", "46858", "46859", "46863", "46868", "46869", "46872", "46873", "46874", "46875", "46876", "46877", "46881", "46884", "46885", "46888", "46889", "46890", "46894", "46896", "46898", "46899", "46901", "46906", "46907", "46908", "46910", "46912", "46913", "46914", "46915", "46916", "46917", "46918", "46922", "46924", "46925", "46926", "46927", "46928", "46930", "46932", "46933", "46937", "46939", "46940", "46946", "46947", "46948", "46951", "46952", "46954", "46956", "46959", "46961", "46962", "46963", "46965", "46966", "46971", "46973", "46975", "46980", "46983", "46986", "46989", "46991", "46993", "46994", "46995", "46998", "46999", "47000", "47003", "47004", "47005", "47009", "47011", "47013", "47015", "47016", "47019", "47021", "47025", "47027", "47029", "47030", "47034", "47035", "47036", "47042", "47043", "47046", "47048", "47049", "47053", "47056", "47057", "47058", "47059", "47060", "47062", "47063", "47064", "47066", "47067", "47069", "47071", "47075", "47076", "47077", "47078", "47079", "47081", "47083", "47085", "47086", "47088", "47089", "47090", "47092", "47093", "47095", "47096", "47098", "47099", "47101", "47103", "47104", "47106", "47108", "47115", "47117", "47119", "47122", "47130", "47131", "47132", "47133", "47135", "47137", "47138", "47139", "47140", "47142", "47144", "47146", "47147", "47148", "47149", "47150", "47151", "47154", "47155", "47166", "47169", "47170", "47172", "47174", "47176", "47177", "47178", "47182", "47183", "47186", "47187", "47188", "47189", "47190", "47191", "47192", "47197", "47199", "47204", "47205", "47206", "47211", "47214", "47215", "47216", "47217", "47218", "47221", "47222", "47223", "47225", "47229", "47231", "47233", "47234", "47235", "47236", "47238", "47239", "47240", "47244", "47245", "47249", "47255", "47257", "47259", "47262", "47263", "47264", "47265", "47266", "47267", "47268", "47270", "47272", "47273", "47274", "47277", "47278", "47279", "47280", "47282", "47283", "47284", "47287", "47292", "47293", "47294", "47295", "47296", "47299", "47300", "47301", "47303", "47305", "47306", "47307", "47309", "47310", "47312", "47315", "47318", "47320", "47321", "47322", "47323", "47326", "47327", "47330", "47332", "47334", "47336", "47337", "47338", "47342", "47344", "47345", "47348", "47351", "47352", "47354", "47355", "47358", "47359", "47360", "47363", "47366", "47370", "47373", "47376", "47384", "47386", "47387", "47388", "47389", "47391", "47392", "47393", "47395", "47399", "47401", "47402", "47403", "47404", "47405", "47406", "47408", "47409", "47412", "47413", "47415", "47417", "47418", "47419", "47421", "47422", "47424", "47425", "47428", "47429", "47432", "47433", "47436", "47438", "47440", "47444", "47445", "47446", "47447", "47448", "47449", "47450", "47451", "47455", "47456", "47457", "47458", "47459", "47460", "47461", "47464", "47465", "47466", "47467", "47468", "47469", "47471", "47477", "47478", "47479", "47480", "47481", "47483", "47484", "47485", "47487", "47491", "47492", "47493", "47497", "47498", "47499", "47502", "47503", "47504", "47505", "47506", "47509", "47513", "47514", "47515", "47517", "47518", "47519", "47520", "47522", "47523", "47525", "47528", "47531", "47533", "47534", "47537", "47539", "47540", "47542", "47547", "47554", "47555", "47556", "47557", "47564", "47565", "47567", "47570", "47571", "47573", "47574", "47575", "47578", "47580", "47582", "47583", "47584", "47588", "47589", "47590", "47594", "47595", "47596", "47599", "47600", "47601", "47603", "47606", "47607", "47613", "47614", "47617", "47618", "47622", "47623", "47628", "47629", "47632", "47633", "47634", "47635", "47637", "47639", "47641", "47646", "47649", "47650", "47653", "47654", "47655", "47658", "47659", "47661", "47662", "47663", "47664", "47665", "47666", "47667", "47668", "47669", "47673", "47674", "47675", "47679", "47680", "47681", "47684", "47685", "47688", "47691", "47694", "47696", "47697", "47698", "47699", "47700", "47701", "47702", "47704", "47706", "47707", "47709", "47711", "47714", "47716", "47717", "47718", "47722", "47724", "47726", "47727", "47728", "47731", "47733", "47736", "47741", "47742", "47743", "47747", "47754", "47764", "47766", "47767", "47768", "47769", "47770", "47772", "47774", "47778", "47780", "47781", "47784", "47785", "47788", "47789", "47795", "47796", "47797", "47798", "47800", "47805", "47809", "47812", "47814", "47816", "47820", "47821", "47826", "47827", "47829", "47830", "47831", "47836", "47837", "47840", "47841", "47845", "47846", "47847", "47850", "47851", "47852", "47853", "47854", "47855", "47856", "47857", "47858", "47861", "47863", "47865", "47866", "47870", "47876", "47878", "47879", "47880", "47881", "47883", "47886", "47889", "47890", "47891", "47892", "47896", "47897", "47898", "47899", "47901", "47903", "47905", "47906", "47907", "47908", "47910", "47912", "47914", "47916", "47917", "47918", "47921", "47923", "47924", "47927", "47930", "47931", "47932", "47933", "47935", "47936", "47937", "47938", "47939", "47940", "47941", "47942", "47945", "47946", "47948", "47951", "47952", "47954", "47957", "47958", "47961", "47962", "47965", "47966", "47967", "47969", "47970", "47971", "47974", "47975", "47976", "47979", "47980", "47985", "47986", "47987", "47988", "47989", "47990", "47991", "47992", "47993", "47995", "47996", "47997", "47998", "48002", "48003", "48006", "48007", "48008", "48010", "48011", "48014", "48017", "48018", "48019", "48020", "48021", "48027", "48029", "48030", "48032", "48033", "48035", "48036", "48037", "48038", "48042", "48043", "48047", "48049", "48050", "48053", "48055", "48056", "48057", "48059", "48062", "48064", "48065", "48066", "48067", "48068", "48070", "48076", "48079", "48080", "48084", "48085", "48086", "48088", "48089", "48090", "48093", "48098", "48100", "48105", "48106", "48110", "48112", "48113", "48114", "48116", "48117", "48119", "48122", "48123", "48124", "48125", "48127", "48128", "48132", "48135", "48136", "48137", "48138", "48139", "48140", "48141", "48142", "48144", "48145", "48146", "48148", "48151", "48152", "48153", "48158", "48159", "48160", "48162", "48164", "48168", "48169", "48170", "48172", "48174", "48176", "48178", "48179", "48186", "48188", "48190", "48191", "48194", "48195", "48197", "48199", "48201", "48203", "48204", "48207", "48208", "48211", "48212", "48216", "48217", "48220", "48221", "48225", "48226", "48229", "48230", "48232", "48233", "48235", "48239", "48242", "48243", "48244", "48246", "48249", "48250", "48251", "48252", "48257", "48258", "48259", "48261", "48264", "48267", "48269", "48270", "48273", "48274", "48280", "48284", "48287", "48289", "48290", "48296", "48298", "48300", "48302", "48303", "48306", "48307", "48309", "48311", "48312", "48313", "48315", "48316", "48319", "48321", "48324", "48326", "48330", "48331", "48332", "48336", "48339", "48341", "48344", "48345", "48346", "48347", "48348", "48349", "48351", "48353", "48360", "48362", "48363", "48364", "48365", "48369", "48370", "48371", "48373", "48375", "48378", "48380", "48381", "48383", "48386", "48388", "48389", "48392", "48393", "48396", "48397", "48398", "48401", "48402", "48404", "48405", "48407", "48409", "48410", "48412", "48414", "48415", "48416", "48417", "48418", "48419", "48422", "48424", "48425", "48427", "48430", "48431", "48434", "48436", "48438", "48439", "48440", "48442", "48443", "48444", "48445", "48446", "48448", "48449", "48450", "48453", "48455", "48456", "48457", "48458", "48462", "48465", "48466", "48467", "48468", "48469", "48470", "48471", "48476", "48477", "48479", "48480", "48482", "48484", "48485", "48486", "48487", "48488", "48489", "48492", "48494", "48495", "48496", "48497", "48498", "48500", "48505", "48506", "48508", "48509", "48511", "48512", "48515", "48517", "48519", "48521", "48522", "48523", "48525", "48526", "48527", "48528", "48532", "48533", "48534", "48536", "48537", "48540", "48542", "48549", "48551", "48552", "48555", "48556", "48557", "48558", "48561", "48562", "48563", "48565", "48566", "48567", "48568", "48570", "48574", "48577", "48578", "48579", "48583", "48584", "48587", "48590", "48591", "48592", "48593", "48596", "48597", "48600", "48603", "48607", "48608", "48610", "48611", "48614", "48615", "48617", "48618", "48620", "48621", "48624", "48625", "48628", "48631", "48632", "48634", "48636", "48637", "48638", "48640", "48641", "48644", "48645", "48647", "48648", "48649", "48650", "48651", "48656", "48657", "48658", "48659", "48661", "48662", "48665", "48666", "48668", "48670", "48672", "48675", "48676", "48677", "48678", "48679", "48683", "48686", "48687", "48688", "48689", "48690", "48691", "48692", "48693", "48694", "48696", "48697", "48699", "48700", "48701", "48703", "48706", "48708", "48711", "48712", "48713", "48714", "48718", "48719", "48721", "48723", "48724", "48726", "48728", "48729", "48731", "48734", "48735", "48737", "48738", "48740", "48741", "48746", "48748", "48750", "48751", "48752", "48753", "48756", "48757", "48759", "48764", "48765", "48766", "48771", "48772", "48773", "48775", "48776", "48778", "48779", "48781", "48782", "48783", "48784", "48785", "48787", "48789", "48790", "48791", "48792", "48793", "48795", "48796", "48800", "48809", "48810", "48811", "48817", "48818", "48819", "48822", "48823", "48824", "48826", "48828", "48831", "48832", "48837", "48838", "48841", "48842", "48843", "48844", "48852", "48853", "48855", "48858", "48861", "48862", "48863", "48865", "48869", "48871", "48876", "48877", "48878", "48880", "48884", "48890", "48891", "48892", "48893", "48899", "48900", "48901", "48902", "48905", "48906", "48907", "48908", "48910", "48915", "48920", "48921", "48923", "48926", "48927", "48928", "48929", "48933", "48934", "48935", "48939", "48942", "48943", "48946", "48947", "48950", "48952", "48953", "48954", "48955", "48957", "48960", "48962", "48963", "48965", "48968", "48971", "48977", "48982", "48983", "48985", "48988", "48989", "48993", "48995", "48996", "48998", "49000", "49001", "49003", "49005", "49010", "49012", "49017", "49018", "49020", "49021", "49022", "49023", "49028", "49029", "49030", "49032", "49034", "49035", "49036", "49037", "49041", "49044", "49052", "49054", "49060", "49063", "49065", "49066", "49068", "49069", "49070", "49071", "49073", "49075", "49076", "49077", "49078", "49080", "49082", "49086", "49087", "49088", "49089", "49092", "49093", "49094", "49095", "49101", "49103", "49104", "49106", "49107", "49108", "49110", "49118", "49120", "49121", "49123", "49124", "49125", "49126", "49127", "49134", "49135", "49137", "49138", "49145", "49146", "49147", "49153", "49154", "49155", "49160", "49161", "49165", "49168", "49172", "49173", "49175", "49176", "49179", "49180", "49181", "49184", "49186", "49187", "49188", "49191", "49202", "49203", "49204", "49205", "49207", "49209", "49213", "49214", "49218", "49220", "49221", "49222", "49227", "49228", "49230", "49233", "49234", "49235", "49236", "49240", "49243", "49244", "49247", "49248", "49249", "49251", "49253", "49254", "49255", "49256", "49257", "49259", "49261", "49263", "49264", "49266", "49269", "49270", "49272", "49273", "49276", "49278", "49280", "49286", "49288", "49291", "49292", "49293", "49295", "49296", "49297", "49299", "49300", "49301", "49302", "49305", "49309", "49310", "49311", "49314", "49315", "49317", "49321", "49326", "49327", "49329", "49330", "49331", "49332", "49333", "49334", "49336", "49337", "49339", "49342", "49343", "49344", "49345", "49346", "49347", "49351", "49353", "49355", "49357", "49360", "49365", "49367", "49371", "49372", "49373", "49374", "49376", "49377", "49378", "49380", "49381", "49386", "49389", "49390", "49391", "49392", "49393", "49394", "49397", "49398", "49400", "49401", "49402", "49403", "49404", "49406", "49410", "49411", "49414", "49415", "49417", "49418", "49420", "49421", "49422", "49423", "49424", "49425", "49426", "49427", "49429", "49433", "49434", "49437", "49439", "49440", "49443", "49445", "49449", "49450", "49451", "49456", "49457", "49458", "49459", "49460", "49461", "49463", "49465", "49466", "49467", "49469", "49470", "49471", "49473", "49475", "49476", "49478", "49482", "49483", "49488", "49490", "49492", "49495", "49497", "49501", "49502", "49506", "49507", "49508", "49515", "49516", "49521", "49526", "49528", "49532", "49534", "49536", "49545", "49546", "49548", "49549", "49552", "49554", "49555", "49557", "49560", "49561", "49562", "49564", "49565", "49569", "49572", "49574", "49576", "49581", "49583", "49586", "49588", "49590", "49592", "49596", "49604", "49612", "49613", "49615", "49616", "49620", "49622", "49623", "49627", "49629", "49630", "49632", "49637", "49640", "49641", "49643", "49644", "49645", "49647", "49649", "49650", "49651", "49652", "49653", "49657", "49659", "49664", "49665", "49669", "49670", "49672", "49673", "49674", "49675", "49676", "49678", "49680", "49681", "49684", "49685", "49686", "49687", "49688", "49693", "49694", "49695", "49701", "49702", "49703", "49705", "49706", "49707", "49710", "49711", "49712", "49713", "49715", "49716", "49717", "49718", "49720", "49722", "49723", "49724", "49725", "49728", "49729", "49733", "49734", "49737", "49738", "49744", "49745", "49746", "49751", "49753", "49754", "49756", "49759", "49763", "49765", "49767", "49769", "49770", "49773", "49774", "49775", "49778", "49781", "49783", "49789", "49790", "49791", "49792", "49795", "49796", "49797", "49798", "49801", "49802", "49803", "49804", "49805", "49806", "49808", "49813", "49814", "49817", "49819", "49820", "49822", "49823", "49826", "49828", "49829", "49831", "49834", "49835", "49836", "49837", "49841", "49842", "49843", "49844", "49846", "49849", "49850", "49852", "49853", "49854", "49856", "49857", "49859", "49860", "49865", "49866", "49868", "49869", "49870", "49871", "49872", "49873", "49874", "49875", "49878", "49879", "49880", "49881", "49884", "49886", "49892", "49894", "49895", "49896", "49899", "49904", "49905", "49907", "49908", "49909", "49910", "49911", "49912", "49914", "49915", "49916", "49917", "49919", "49920", "49923", "49927", "49930", "49931", "49934", "49937", "49938", "49939", "49940", "49941", "49942", "49943", "49945", "49947", "49948", "49950", "49951", "49954", "49955", "49958", "49960", "49961", "49962", "49963", "49968", "49970", "49973", "49975", "49976", "49978", "49979", "49982", "49985", "49986", "49991", "49993", "49995", "49996", "49997", "49998", "49999"]] -} \ No newline at end of file diff --git a/datasets/__init__.py b/datasets/__init__.py index f96d0ef..d739440 100644 --- a/datasets/__init__.py +++ b/datasets/__init__.py @@ -3,3 +3,4 @@ ################################################## from .get_dataset_with_transform import get_datasets, get_nas_search_loaders from .SearchDatasetWrap import SearchDataset +from .data import get_data diff --git a/datasets/data.py b/datasets/data.py new file mode 100644 index 0000000..e9d8959 --- /dev/null +++ b/datasets/data.py @@ -0,0 +1,69 @@ +from datasets import get_datasets +from config_utils import load_config +import torch +import torchvision + +class AddGaussianNoise(object): + def __init__(self, mean=0., std=0.001): + self.std = std + self.mean = mean + + def __call__(self, tensor): + return tensor + torch.randn(tensor.size()) * self.std + self.mean + + def __repr__(self): + return self.__class__.__name__ + '(mean={0}, std={1})'.format(self.mean, self.std) + + + + +class RepeatSampler(torch.utils.data.sampler.Sampler): + def __init__(self, samp, repeat): + self.samp = samp + self.repeat = repeat + def __iter__(self): + for i in self.samp: + for j in range(self.repeat): + yield i + def __len__(self): + return self.repeat*len(self.samp) + + +def get_data(dataset, data_loc, trainval, batch_size, augtype, repeat, args, pin_memory=True): + train_data, valid_data, xshape, class_num = get_datasets(dataset, data_loc, cutout=0) + if augtype == 'gaussnoise': + train_data.transform.transforms = train_data.transform.transforms[2:] + train_data.transform.transforms.append(AddGaussianNoise(std=args.sigma)) + elif augtype == 'cutout': + train_data.transform.transforms = train_data.transform.transforms[2:] + train_data.transform.transforms.append(torchvision.transforms.RandomErasing(p=0.9, scale=(0.02, 0.04))) + elif augtype == 'none': + train_data.transform.transforms = train_data.transform.transforms[2:] + + if dataset == 'cifar10': + acc_type = 'ori-test' + val_acc_type = 'x-valid' + + else: + acc_type = 'x-test' + val_acc_type = 'x-valid' + + if trainval and 'cifar10' in dataset: + cifar_split = load_config('config_utils/cifar-split.txt', None, None) + train_split, valid_split = cifar_split.train, cifar_split.valid + if repeat > 0: + train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, + num_workers=0, pin_memory=pin_memory, sampler= RepeatSampler(torch.utils.data.sampler.SubsetRandomSampler(train_split), repeat)) + else: + train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, + num_workers=0, pin_memory=pin_memory, sampler= torch.utils.data.sampler.SubsetRandomSampler(train_split)) + + + else: + if repeat > 0: + train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, #shuffle=True, + num_workers=0, pin_memory=pin_memory, sampler= RepeatSampler(torch.utils.data.sampler.SubsetRandomSampler(range(len(train_data))), repeat)) + else: + train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True, + num_workers=0, pin_memory=pin_memory) + return train_loader diff --git a/datasets/get_dataset_with_transform.py b/datasets/get_dataset_with_transform.py index 7a79867..48513ff 100644 --- a/datasets/get_dataset_with_transform.py +++ b/datasets/get_dataset_with_transform.py @@ -16,7 +16,9 @@ from config_utils import load_config Dataset2Class = {'cifar10' : 10, 'cifar100': 100, + 'fake':10, 'imagenet-1k-s':1000, + 'imagenette2' : 10, 'imagenet-1k' : 1000, 'ImageNet16' : 1000, 'ImageNet16-150': 150, @@ -98,8 +100,13 @@ def get_datasets(name, root, cutout): elif name == 'cifar100': mean = [x / 255 for x in [129.3, 124.1, 112.4]] std = [x / 255 for x in [68.2, 65.4, 70.4]] + elif name == 'fake': + mean = [x / 255 for x in [129.3, 124.1, 112.4]] + std = [x / 255 for x in [68.2, 65.4, 70.4]] elif name.startswith('imagenet-1k'): mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] + elif name.startswith('imagenette'): + mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] elif name.startswith('ImageNet16'): mean = [x / 255 for x in [122.68, 116.66, 104.01]] std = [x / 255 for x in [63.22, 61.26 , 65.09]] @@ -113,6 +120,12 @@ def get_datasets(name, root, cutout): train_transform = transforms.Compose(lists) test_transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean, std)]) xshape = (1, 3, 32, 32) + elif name == 'fake': + lists = [transforms.RandomHorizontalFlip(), transforms.RandomCrop(32, padding=4), transforms.ToTensor(), transforms.Normalize(mean, std)] + if cutout > 0 : lists += [CUTOUT(cutout)] + train_transform = transforms.Compose(lists) + test_transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean, std)]) + xshape = (1, 3, 32, 32) elif name.startswith('ImageNet16'): lists = [transforms.RandomHorizontalFlip(), transforms.RandomCrop(16, padding=2), transforms.ToTensor(), transforms.Normalize(mean, std)] if cutout > 0 : lists += [CUTOUT(cutout)] @@ -125,6 +138,15 @@ def get_datasets(name, root, cutout): train_transform = transforms.Compose(lists) test_transform = transforms.Compose([transforms.CenterCrop(80), transforms.ToTensor(), transforms.Normalize(mean, std)]) xshape = (1, 3, 32, 32) + elif name.startswith('imagenette'): + normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) + xlists = [] + xlists.append( transforms.ToTensor() ) + xlists.append( normalize ) + #train_transform = transforms.Compose(xlists) + train_transform = transforms.Compose([normalize, normalize, transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), normalize]) + test_transform = transforms.Compose([normalize, normalize, transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), normalize]) + xshape = (1, 3, 224, 224) elif name.startswith('imagenet-1k'): normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) if name == 'imagenet-1k': @@ -156,6 +178,12 @@ def get_datasets(name, root, cutout): train_data = dset.CIFAR100(root, train=True , transform=train_transform, download=True) test_data = dset.CIFAR100(root, train=False, transform=test_transform , download=True) assert len(train_data) == 50000 and len(test_data) == 10000 + elif name == 'fake': + train_data = dset.FakeData(size=50000, image_size=(3, 32, 32), transform=train_transform) + test_data = dset.FakeData(size=10000, image_size=(3, 32, 32), transform=test_transform) + elif name.startswith('imagenette2'): + train_data = dset.ImageFolder(osp.join(root, 'train'), train_transform) + test_data = dset.ImageFolder(osp.join(root, 'val'), test_transform) elif name.startswith('imagenet-1k'): train_data = dset.ImageFolder(osp.join(root, 'train'), train_transform) test_data = dset.ImageFolder(osp.join(root, 'val'), test_transform) diff --git a/env.yml b/env.yml new file mode 100644 index 0000000..4dd828d --- /dev/null +++ b/env.yml @@ -0,0 +1,24 @@ +name: naswot2 +channels: + - conda-forge + - pytorch +dependencies: + - python=3.7 + - numpy + - matplotlib + - seaborn + - pandas + - xlrd + - scipy + - pip + - scikit-learn + - scikit-image + - pytorch::pytorch==1.6.0 + - pytorch::torchvision==0.7.0 + - cudatoolkit=9.2 + - tqdm + - pip: + - tensorflow-gpu==1.15 + - yacs + - simplejson + - "--editable=git+https://github.com/google-research/nasbench#egg=nasbench-master" diff --git a/environment.yml b/environment.yml deleted file mode 100644 index 019b5df..0000000 --- a/environment.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: nas-wot -channels: - - pytorch - - defaults -dependencies: - - _libgcc_mutex=0.1=main - - blas=1.0=mkl - - ca-certificates=2020.1.1=0 - - certifi=2020.4.5.1=py38_0 - - cudatoolkit=10.2.89=hfd86e86_1 - - freetype=2.9.1=h8a8886c_1 - - intel-openmp=2020.1=217 - - jpeg=9b=h024ee3a_2 - - ld_impl_linux-64=2.33.1=h53a641e_7 - - libedit=3.1.20181209=hc058e9b_0 - - libffi=3.3=he6710b0_1 - - libgcc-ng=9.1.0=hdf63c60_0 - - libgfortran-ng=7.3.0=hdf63c60_0 - - libpng=1.6.37=hbc83047_0 - - libstdcxx-ng=9.1.0=hdf63c60_0 - - libtiff=4.1.0=h2733197_1 - - lz4-c=1.9.2=he6710b0_0 - - mkl=2020.1=217 - - mkl-service=2.3.0=py38he904b0f_0 - - mkl_fft=1.0.15=py38ha843d7b_0 - - mkl_random=1.1.1=py38h0573a6f_0 - - ncurses=6.2=he6710b0_1 - - ninja=1.9.0=py38hfd86e86_0 - - numpy=1.18.1=py38h4f9e942_0 - - numpy-base=1.18.1=py38hde5b4d6_1 - - olefile=0.46=py_0 - - openssl=1.1.1g=h7b6447c_0 - - pandas=1.0.3=py38h0573a6f_0 - - pillow=7.1.2=py38hb39fc2d_0 - - pip=20.0.2=py38_3 - - python=3.8.3=hcff3b4d_0 - - python-dateutil=2.8.1=py_0 - - pytorch=1.5.0=py3.8_cuda10.2.89_cudnn7.6.5_0 - - pytz=2020.1=py_0 - - readline=8.0=h7b6447c_0 - - setuptools=46.4.0=py38_0 - - six=1.14.0=py38_0 - - sqlite=3.31.1=h62c20be_1 - - tk=8.6.8=hbc83047_0 - - torchvision=0.6.0=py38_cu102 - - tqdm=4.46.0=py_0 - - wheel=0.34.2=py38_0 - - xz=5.2.5=h7b6447c_0 - - zlib=1.2.11=h7b6447c_3 - - zstd=1.4.4=h0b5b093_3 - - pip: - - argparse==1.4.0 - - nas-bench-201==1.3 - - tabulate==0.8.7 diff --git a/models/cell_infers/tiny_network.py b/models/cell_infers/tiny_network.py index 6dd72b3..333bc92 100644 --- a/models/cell_infers/tiny_network.py +++ b/models/cell_infers/tiny_network.py @@ -55,4 +55,4 @@ class TinyNetwork(nn.Module): out = out.view(out.size(0), -1) logits = self.classifier(out) - return out, logits + return logits, out diff --git a/nas_101_api/__init__.py b/nas_101_api/__init__.py new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/nas_101_api/__init__.py @@ -0,0 +1 @@ + diff --git a/nas_101_api/base_ops.py b/nas_101_api/base_ops.py new file mode 100644 index 0000000..90affb2 --- /dev/null +++ b/nas_101_api/base_ops.py @@ -0,0 +1,65 @@ +"""Base operations used by the modules in this search space.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import torch +import torch.nn as nn +import torch.nn.functional as F + +class ConvBnRelu(nn.Module): + def __init__(self, in_channels, out_channels, kernel_size=1, stride=1, padding=0): + super(ConvBnRelu, self).__init__() + + self.conv_bn_relu = nn.Sequential( + #nn.ReLU(), + nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding, bias=False), + nn.BatchNorm2d(out_channels), + #nn.ReLU(inplace=True) + nn.ReLU() + ) + + def forward(self, x): + return self.conv_bn_relu(x) + +class Conv3x3BnRelu(nn.Module): + """3x3 convolution with batch norm and ReLU activation.""" + def __init__(self, in_channels, out_channels): + super(Conv3x3BnRelu, self).__init__() + + self.conv3x3 = ConvBnRelu(in_channels, out_channels, 3, 1, 1) + + def forward(self, x): + x = self.conv3x3(x) + return x + +class Conv1x1BnRelu(nn.Module): + """1x1 convolution with batch norm and ReLU activation.""" + def __init__(self, in_channels, out_channels): + super(Conv1x1BnRelu, self).__init__() + + self.conv1x1 = ConvBnRelu(in_channels, out_channels, 1, 1, 0) + + def forward(self, x): + x = self.conv1x1(x) + return x + +class MaxPool3x3(nn.Module): + """3x3 max pool with no subsampling.""" + def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=1): + super(MaxPool3x3, self).__init__() + + self.maxpool = nn.MaxPool2d(kernel_size, stride, padding) + #self.maxpool = nn.AvgPool2d(kernel_size, stride, padding) + + def forward(self, x): + x = self.maxpool(x) + return x + +# Commas should not be used in op names +OP_MAP = { + 'conv3x3-bn-relu': Conv3x3BnRelu, + 'conv1x1-bn-relu': Conv1x1BnRelu, + 'maxpool3x3': MaxPool3x3 +} diff --git a/nas_101_api/graph_util.py b/nas_101_api/graph_util.py new file mode 100644 index 0000000..120ad1e --- /dev/null +++ b/nas_101_api/graph_util.py @@ -0,0 +1,167 @@ +# Copyright 2019 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. + +"""Utility functions used by generate_graph.py.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import hashlib +import itertools + +import numpy as np + + +def gen_is_edge_fn(bits): + """Generate a boolean function for the edge connectivity. + + Given a bitstring FEDCBA and a 4x4 matrix, the generated matrix is + [[0, A, B, D], + [0, 0, C, E], + [0, 0, 0, F], + [0, 0, 0, 0]] + + Note that this function is agnostic to the actual matrix dimension due to + order in which elements are filled out (column-major, starting from least + significant bit). For example, the same FEDCBA bitstring (0-padded) on a 5x5 + matrix is + [[0, A, B, D, 0], + [0, 0, C, E, 0], + [0, 0, 0, F, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]] + + Args: + bits: integer which will be interpreted as a bit mask. + + Returns: + vectorized function that returns True when an edge is present. + """ + def is_edge(x, y): + """Is there an edge from x to y (0-indexed)?""" + if x >= y: + return 0 + # Map x, y to index into bit string + index = x + (y * (y - 1) // 2) + return (bits >> index) % 2 == 1 + + return np.vectorize(is_edge) + + +def is_full_dag(matrix): + """Full DAG == all vertices on a path from vert 0 to (V-1). + + i.e. no disconnected or "hanging" vertices. + + It is sufficient to check for: + 1) no rows of 0 except for row V-1 (only output vertex has no out-edges) + 2) no cols of 0 except for col 0 (only input vertex has no in-edges) + + Args: + matrix: V x V upper-triangular adjacency matrix + + Returns: + True if the there are no dangling vertices. + """ + shape = np.shape(matrix) + + rows = matrix[:shape[0]-1, :] == 0 + rows = np.all(rows, axis=1) # Any row with all 0 will be True + rows_bad = np.any(rows) + + cols = matrix[:, 1:] == 0 + cols = np.all(cols, axis=0) # Any col with all 0 will be True + cols_bad = np.any(cols) + + return (not rows_bad) and (not cols_bad) + + +def num_edges(matrix): + """Computes number of edges in adjacency matrix.""" + return np.sum(matrix) + + +def hash_module(matrix, labeling): + """Computes a graph-invariance MD5 hash of the matrix and label pair. + + Args: + matrix: np.ndarray square upper-triangular adjacency matrix. + labeling: list of int labels of length equal to both dimensions of + matrix. + + Returns: + MD5 hash of the matrix and labeling. + """ + vertices = np.shape(matrix)[0] + in_edges = np.sum(matrix, axis=0).tolist() + out_edges = np.sum(matrix, axis=1).tolist() + + assert len(in_edges) == len(out_edges) == len(labeling) + hashes = list(zip(out_edges, in_edges, labeling)) + hashes = [hashlib.md5(str(h).encode('utf-8')).hexdigest() for h in hashes] + # Computing this up to the diameter is probably sufficient but since the + # operation is fast, it is okay to repeat more times. + for _ in range(vertices): + new_hashes = [] + for v in range(vertices): + in_neighbors = [hashes[w] for w in range(vertices) if matrix[w, v]] + out_neighbors = [hashes[w] for w in range(vertices) if matrix[v, w]] + new_hashes.append(hashlib.md5( + (''.join(sorted(in_neighbors)) + '|' + + ''.join(sorted(out_neighbors)) + '|' + + hashes[v]).encode('utf-8')).hexdigest()) + hashes = new_hashes + fingerprint = hashlib.md5(str(sorted(hashes)).encode('utf-8')).hexdigest() + + return fingerprint + + +def permute_graph(graph, label, permutation): + """Permutes the graph and labels based on permutation. + + Args: + graph: np.ndarray adjacency matrix. + label: list of labels of same length as graph dimensions. + permutation: a permutation list of ints of same length as graph dimensions. + + Returns: + np.ndarray where vertex permutation[v] is vertex v from the original graph + """ + # vertex permutation[v] in new graph is vertex v in the old graph + forward_perm = zip(permutation, list(range(len(permutation)))) + inverse_perm = [x[1] for x in sorted(forward_perm)] + edge_fn = lambda x, y: graph[inverse_perm[x], inverse_perm[y]] == 1 + new_matrix = np.fromfunction(np.vectorize(edge_fn), + (len(label), len(label)), + dtype=np.int8) + new_label = [label[inverse_perm[i]] for i in range(len(label))] + return new_matrix, new_label + + +def is_isomorphic(graph1, graph2): + """Exhaustively checks if 2 graphs are isomorphic.""" + matrix1, label1 = np.array(graph1[0]), graph1[1] + matrix2, label2 = np.array(graph2[0]), graph2[1] + assert np.shape(matrix1) == np.shape(matrix2) + assert len(label1) == len(label2) + + vertices = np.shape(matrix1)[0] + # Note: input and output in our constrained graphs always map to themselves + # but this script does not enforce that. + for perm in itertools.permutations(range(0, vertices)): + pmatrix1, plabel1 = permute_graph(matrix1, label1, perm) + if np.array_equal(pmatrix1, matrix2) and plabel1 == label2: + return True + + return False diff --git a/nas_101_api/model.py b/nas_101_api/model.py new file mode 100644 index 0000000..997708c --- /dev/null +++ b/nas_101_api/model.py @@ -0,0 +1,252 @@ +"""Builds the Pytorch computational graph. + +Tensors flowing into a single vertex are added together for all vertices +except the output, which is concatenated instead. Tensors flowing out of input +are always added. + +If interior edge channels don't match, drop the extra channels (channels are +guaranteed non-decreasing). Tensors flowing out of the input as always +projected instead. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +import math + +from .base_ops import * + +import torch +import torch.nn as nn +import torch.nn.functional as F + +class Network(nn.Module): + def __init__(self, spec, args, searchspace=[]): + super(Network, self).__init__() + + self.layers = nn.ModuleList([]) + + in_channels = 3 + out_channels = args.stem_out_channels + + # initial stem convolution + stem_conv = ConvBnRelu(in_channels, out_channels, 3, 1, 1) + self.layers.append(stem_conv) + + in_channels = out_channels + for stack_num in range(args.num_stacks): + if stack_num > 0: + #downsample = nn.MaxPool2d(kernel_size=3, stride=2) + downsample = nn.MaxPool2d(kernel_size=2, stride=2) + #downsample = nn.AvgPool2d(kernel_size=2, stride=2) + #downsample = nn.Conv2d(in_channels, out_channels, kernel_size=(2, 2), stride=2) + self.layers.append(downsample) + + out_channels *= 2 + + for module_num in range(args.num_modules_per_stack): + cell = Cell(spec, in_channels, out_channels) + self.layers.append(cell) + in_channels = out_channels + + self.classifier = nn.Linear(out_channels, args.num_labels) + + # for DARTS search + num_edge = np.shape(spec.matrix)[0] + self.arch_parameters = nn.Parameter( 1e-3*torch.randn(num_edge, len(searchspace))) + + self._initialize_weights() + + def forward(self, x, get_ints=True): + ints = [] + for _, layer in enumerate(self.layers): + x = layer(x) + ints.append(x) + out = torch.mean(x, (2, 3)) + ints.append(out) + out = self.classifier(out) + if get_ints: + return out, ints[-1] + else: + return out + + def _initialize_weights(self): + for m in self.modules(): + if isinstance(m, nn.Conv2d): + n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels + m.weight.data.normal_(0, math.sqrt(2.0 / n)) + if m.bias is not None: + m.bias.data.zero_() + pass + elif isinstance(m, nn.BatchNorm2d): + m.weight.data.fill_(1) + m.bias.data.zero_() + pass + elif isinstance(m, nn.Linear): + n = m.weight.size(1) + m.weight.data.normal_(0, 0.01) + m.bias.data.zero_() + pass + + def get_weights(self): + xlist = [] + for m in self.modules(): + xlist.append(m.parameters()) + return xlist + + def get_alphas(self): + return [self.arch_parameters] + + def genotype(self): + return str(spec) + + +class Cell(nn.Module): + """ + Builds the model using the adjacency matrix and op labels specified. Channels + controls the module output channel count but the interior channels are + determined via equally splitting the channel count whenever there is a + concatenation of Tensors. + """ + def __init__(self, spec, in_channels, out_channels): + super(Cell, self).__init__() + + self.spec = spec + self.num_vertices = np.shape(self.spec.matrix)[0] + + # vertex_channels[i] = number of output channels of vertex i + self.vertex_channels = ComputeVertexChannels(in_channels, out_channels, self.spec.matrix) + #self.vertex_channels = [in_channels] + [out_channels] * (self.num_vertices - 1) + + # operation for each node + self.vertex_op = nn.ModuleList([None]) + for t in range(1, self.num_vertices-1): + op = OP_MAP[spec.ops[t]](self.vertex_channels[t], self.vertex_channels[t]) + self.vertex_op.append(op) + + # operation for input on each vertex + self.input_op = nn.ModuleList([None]) + for t in range(1, self.num_vertices): + if self.spec.matrix[0, t]: + self.input_op.append(Projection(in_channels, self.vertex_channels[t])) + else: + self.input_op.append(None) + + def forward(self, x): + tensors = [x] + out_concat = [] + for t in range(1, self.num_vertices-1): + fan_in = [Truncate(tensors[src], self.vertex_channels[t]) for src in range(1, t) if self.spec.matrix[src, t]] + fan_in_inds = [src for src in range(1, t) if self.spec.matrix[src, t]] + + if self.spec.matrix[0, t]: + fan_in.append(self.input_op[t](x)) + fan_in_inds = [0] + fan_in_inds + + # perform operation on node + #vertex_input = torch.stack(fan_in, dim=0).sum(dim=0) + vertex_input = sum(fan_in) + #vertex_input = sum(fan_in) / len(fan_in) + vertex_output = self.vertex_op[t](vertex_input) + + tensors.append(vertex_output) + if self.spec.matrix[t, self.num_vertices-1]: + out_concat.append(tensors[t]) + + if not out_concat: # empty list + assert self.spec.matrix[0, self.num_vertices-1] + outputs = self.input_op[self.num_vertices-1](tensors[0]) + else: + if len(out_concat) == 1: + outputs = out_concat[0] + else: + outputs = torch.cat(out_concat, 1) + + if self.spec.matrix[0, self.num_vertices-1]: + outputs += self.input_op[self.num_vertices-1](tensors[0]) + + #if self.spec.matrix[0, self.num_vertices-1]: + # out_concat.append(self.input_op[self.num_vertices-1](tensors[0])) + #outputs = sum(out_concat) / len(out_concat) + + return outputs + +def Projection(in_channels, out_channels): + """1x1 projection (as in ResNet) followed by batch normalization and ReLU.""" + return ConvBnRelu(in_channels, out_channels, 1) + +def Truncate(inputs, channels): + """Slice the inputs to channels if necessary.""" + input_channels = inputs.size()[1] + if input_channels < channels: + raise ValueError('input channel < output channels for truncate') + elif input_channels == channels: + return inputs # No truncation necessary + else: + # Truncation should only be necessary when channel division leads to + # vertices with +1 channels. The input vertex should always be projected to + # the minimum channel count. + assert input_channels - channels == 1 + return inputs[:, :channels, :, :] + +def ComputeVertexChannels(in_channels, out_channels, matrix): + """Computes the number of channels at every vertex. + + Given the input channels and output channels, this calculates the number of + channels at each interior vertex. Interior vertices have the same number of + channels as the max of the channels of the vertices it feeds into. The output + channels are divided amongst the vertices that are directly connected to it. + When the division is not even, some vertices may receive an extra channel to + compensate. + + Returns: + list of channel counts, in order of the vertices. + """ + num_vertices = np.shape(matrix)[0] + + vertex_channels = [0] * num_vertices + vertex_channels[0] = in_channels + vertex_channels[num_vertices - 1] = out_channels + + if num_vertices == 2: + # Edge case where module only has input and output vertices + return vertex_channels + + # Compute the in-degree ignoring input, axis 0 is the src vertex and axis 1 is + # the dst vertex. Summing over 0 gives the in-degree count of each vertex. + in_degree = np.sum(matrix[1:], axis=0) + interior_channels = out_channels // in_degree[num_vertices - 1] + correction = out_channels % in_degree[num_vertices - 1] # Remainder to add + + # Set channels of vertices that flow directly to output + for v in range(1, num_vertices - 1): + if matrix[v, num_vertices - 1]: + vertex_channels[v] = interior_channels + if correction: + vertex_channels[v] += 1 + correction -= 1 + + # Set channels for all other vertices to the max of the out edges, going + # backwards. (num_vertices - 2) index skipped because it only connects to + # output. + for v in range(num_vertices - 3, 0, -1): + if not matrix[v, num_vertices - 1]: + for dst in range(v + 1, num_vertices - 1): + if matrix[v, dst]: + vertex_channels[v] = max(vertex_channels[v], vertex_channels[dst]) + assert vertex_channels[v] > 0 + + # Sanity check, verify that channels never increase and final channels add up. + final_fan_in = 0 + for v in range(1, num_vertices - 1): + if matrix[v, num_vertices - 1]: + final_fan_in += vertex_channels[v] + for dst in range(v + 1, num_vertices - 1): + if matrix[v, dst]: + assert vertex_channels[v] >= vertex_channels[dst] + assert final_fan_in == out_channels or num_vertices == 2 + # num_vertices == 2 means only input/output nodes, so 0 fan-in + + return vertex_channels diff --git a/nas_101_api/model_spec.py b/nas_101_api/model_spec.py new file mode 100644 index 0000000..f5bfe4a --- /dev/null +++ b/nas_101_api/model_spec.py @@ -0,0 +1,152 @@ +"""Model specification for module connectivity individuals. + +This module handles pruning the unused parts of the computation graph but should +avoid creating any TensorFlow models (this is done inside model_builder.py). +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import copy +import numpy as np + +from . import graph_util + +# Graphviz is optional and only required for visualization. +try: + import graphviz # pylint: disable=g-import-not-at-top +except ImportError: + pass + + +class ModelSpec(object): + """Model specification given adjacency matrix and labeling.""" + + def __init__(self, matrix, ops, data_format='channels_last'): + """Initialize the module spec. + + Args: + matrix: ndarray or nested list with shape [V, V] for the adjacency matrix. + ops: V-length list of labels for the base ops used. The first and last + elements are ignored because they are the input and output vertices + which have no operations. The elements are retained to keep consistent + indexing. + data_format: channels_last or channels_first. + + Raises: + ValueError: invalid matrix or ops + """ + if not isinstance(matrix, np.ndarray): + matrix = np.array(matrix) + shape = np.shape(matrix) + if len(shape) != 2 or shape[0] != shape[1]: + raise ValueError('matrix must be square') + if shape[0] != len(ops): + raise ValueError('length of ops must match matrix dimensions') + if not is_upper_triangular(matrix): + raise ValueError('matrix must be upper triangular') + + # Both the original and pruned matrices are deep copies of the matrix and + # ops so any changes to those after initialization are not recognized by the + # spec. + self.original_matrix = copy.deepcopy(matrix) + self.original_ops = copy.deepcopy(ops) + + self.matrix = copy.deepcopy(matrix) + self.ops = copy.deepcopy(ops) + self.valid_spec = True + self._prune() + + self.data_format = data_format + + def _prune(self): + """Prune the extraneous parts of the graph. + + General procedure: + 1) Remove parts of graph not connected to input. + 2) Remove parts of graph not connected to output. + 3) Reorder the vertices so that they are consecutive after steps 1 and 2. + + These 3 steps can be combined by deleting the rows and columns of the + vertices that are not reachable from both the input and output (in reverse). + """ + num_vertices = np.shape(self.original_matrix)[0] + + # DFS forward from input + visited_from_input = set([0]) + frontier = [0] + while frontier: + top = frontier.pop() + for v in range(top + 1, num_vertices): + if self.original_matrix[top, v] and v not in visited_from_input: + visited_from_input.add(v) + frontier.append(v) + + # DFS backward from output + visited_from_output = set([num_vertices - 1]) + frontier = [num_vertices - 1] + while frontier: + top = frontier.pop() + for v in range(0, top): + if self.original_matrix[v, top] and v not in visited_from_output: + visited_from_output.add(v) + frontier.append(v) + + # Any vertex that isn't connected to both input and output is extraneous to + # the computation graph. + extraneous = set(range(num_vertices)).difference( + visited_from_input.intersection(visited_from_output)) + + # If the non-extraneous graph is less than 2 vertices, the input is not + # connected to the output and the spec is invalid. + if len(extraneous) > num_vertices - 2: + self.matrix = None + self.ops = None + self.valid_spec = False + return + + self.matrix = np.delete(self.matrix, list(extraneous), axis=0) + self.matrix = np.delete(self.matrix, list(extraneous), axis=1) + for index in sorted(extraneous, reverse=True): + del self.ops[index] + + def hash_spec(self, canonical_ops): + """Computes the isomorphism-invariant graph hash of this spec. + + Args: + canonical_ops: list of operations in the canonical ordering which they + were assigned (i.e. the order provided in the config['available_ops']). + + Returns: + MD5 hash of this spec which can be used to query the dataset. + """ + # Invert the operations back to integer label indices used in graph gen. + labeling = [-1] + [canonical_ops.index(op) for op in self.ops[1:-1]] + [-2] + return graph_util.hash_module(self.matrix, labeling) + + def visualize(self): + """Creates a dot graph. Can be visualized in colab directly.""" + num_vertices = np.shape(self.matrix)[0] + g = graphviz.Digraph() + g.node(str(0), 'input') + for v in range(1, num_vertices - 1): + g.node(str(v), self.ops[v]) + g.node(str(num_vertices - 1), 'output') + + for src in range(num_vertices - 1): + for dst in range(src + 1, num_vertices): + if self.matrix[src, dst]: + g.edge(str(src), str(dst)) + + return g + + +def is_upper_triangular(matrix): + """True if matrix is 0 on diagonal and below.""" + for src in range(np.shape(matrix)[0]): + for dst in range(0, src + 1): + if matrix[src, dst] != 0: + return False + + return True diff --git a/nas_201_api/__init__.py b/nas_201_api/__init__.py new file mode 100644 index 0000000..e87f2fd --- /dev/null +++ b/nas_201_api/__init__.py @@ -0,0 +1,15 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +##################################################################### +# This API will not be updated after 2020.09.16. # +# Please use our new API in NATS-Bench, which is # +# more efficient and contains info of more architecture candidates. # +##################################################################### +from .api_utils import ArchResults, ResultsCount +from .api_201 import NASBench201API + +# NAS_BENCH_201_API_VERSION="v1.1" # [2020.02.25] +# NAS_BENCH_201_API_VERSION="v1.2" # [2020.03.09] +# NAS_BENCH_201_API_VERSION="v1.3" # [2020.03.16] +NAS_BENCH_201_API_VERSION="v2.0" # [2020.06.30] + diff --git a/nas_201_api/api.py b/nas_201_api/api.py new file mode 100644 index 0000000..bc36ac7 --- /dev/null +++ b/nas_201_api/api.py @@ -0,0 +1,830 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +############################################################################################ +# NAS-Bench-201: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 # +############################################################################################ +# [2020.02.25] NAS-Bench-201-v1_0-e61699.pth : 6219 architectures are trained once, 1621 architectures are trained twice, 7785 architectures are trained three times. `LESS` only supports CIFAR10-VALID. +# [2020.03.08] Next version (coming soon) +# +# +import os, copy, random, torch, numpy as np +from typing import List, Text, Union, Dict +from collections import OrderedDict, defaultdict + + +def print_information(information, extra_info=None, show=False): + dataset_names = information.get_dataset_names() + strings = [information.arch_str, 'datasets : {:}, extra-info : {:}'.format(dataset_names, extra_info)] + def metric2str(loss, acc): + return 'loss = {:.3f}, top1 = {:.2f}%'.format(loss, acc) + + for ida, dataset in enumerate(dataset_names): + metric = information.get_compute_costs(dataset) + flop, param, latency = metric['flops'], metric['params'], metric['latency'] + str1 = '{:14s} FLOP={:6.2f} M, Params={:.3f} MB, latency={:} ms.'.format(dataset, flop, param, '{:.2f}'.format(latency*1000) if latency is not None and latency > 0 else None) + train_info = information.get_metrics(dataset, 'train') + if dataset == 'cifar10-valid': + valid_info = information.get_metrics(dataset, 'x-valid') + str2 = '{:14s} train : [{:}], valid : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy'])) + elif dataset == 'cifar10': + test__info = information.get_metrics(dataset, 'ori-test') + str2 = '{:14s} train : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + else: + valid_info = information.get_metrics(dataset, 'x-valid') + test__info = information.get_metrics(dataset, 'x-test') + str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + strings += [str1, str2] + if show: print('\n'.join(strings)) + return strings + +""" +This is the class for API of NAS-Bench-201. +""" +class NASBench201API(object): + + """ The initialization function that takes the dataset file path (or a dict loaded from that path) as input. """ + def __init__(self, file_path_or_dict: Union[Text, Dict], verbose: bool=True): + if isinstance(file_path_or_dict, str): + if verbose: print('try to create the NAS-Bench-201 api from {:}'.format(file_path_or_dict)) + assert os.path.isfile(file_path_or_dict), 'invalid path : {:}'.format(file_path_or_dict) + file_path_or_dict = torch.load(file_path_or_dict) + elif isinstance(file_path_or_dict, dict): + file_path_or_dict = copy.deepcopy( file_path_or_dict ) + else: raise ValueError('invalid type : {:} not in [str, dict]'.format(type(file_path_or_dict))) + assert isinstance(file_path_or_dict, dict), 'It should be a dict instead of {:}'.format(type(file_path_or_dict)) + keys = ('meta_archs', 'arch2infos', 'evaluated_indexes') + for key in keys: assert key in file_path_or_dict, 'Can not find key[{:}] in the dict'.format(key) + self.meta_archs = copy.deepcopy( file_path_or_dict['meta_archs'] ) + self.arch2infos_less = OrderedDict() + self.arch2infos_full = OrderedDict() + for xkey in sorted(list(file_path_or_dict['arch2infos'].keys())): + all_info = file_path_or_dict['arch2infos'][xkey] + self.arch2infos_less[xkey] = ArchResults.create_from_state_dict( all_info['less'] ) + self.arch2infos_full[xkey] = ArchResults.create_from_state_dict( all_info['full'] ) + self.evaluated_indexes = sorted(list(file_path_or_dict['evaluated_indexes'])) + self.archstr2index = {} + for idx, arch in enumerate(self.meta_archs): + #assert arch.tostr() not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch.tostr()]) + assert arch not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch]) + self.archstr2index[ arch ] = idx + + def __getitem__(self, index: int): + return copy.deepcopy( self.meta_archs[index] ) + + def __len__(self): + return len(self.meta_archs) + + def __repr__(self): + return ('{name}({num}/{total} architectures)'.format(name=self.__class__.__name__, num=len(self.evaluated_indexes), total=len(self.meta_archs))) + + def random(self): + """Return a random index of all architectures.""" + return random.randint(0, len(self.meta_archs)-1) + + # This function is used to query the index of an architecture in the search space. + # The input arch can be an architecture string such as '|nor_conv_3x3~0|+|nor_conv_3x3~0|avg_pool_3x3~1|+|skip_connect~0|nor_conv_3x3~1|skip_connect~2|' + # or an instance that has the 'tostr' function that can generate the architecture string. + # This function will return the index. + # If return -1, it means this architecture is not in the search space. + # Otherwise, it will return an int in [0, the-number-of-candidates-in-the-search-space). + def query_index_by_arch(self, arch): + if isinstance(arch, str): + if arch in self.archstr2index: arch_index = self.archstr2index[ arch ] + else : arch_index = -1 + elif hasattr(arch, 'tostr'): + if arch.tostr() in self.archstr2index: arch_index = self.archstr2index[ arch.tostr() ] + else : arch_index = -1 + else: arch_index = -1 + return arch_index + + # Overwrite all information of the 'index'-th architecture in the search space. + # It will load its data from 'archive_root'. + def reload(self, archive_root: Text, index: int): + assert os.path.isdir(archive_root), 'invalid directory : {:}'.format(archive_root) + xfile_path = os.path.join(archive_root, '{:06d}-FULL.pth'.format(index)) + assert 0 <= index < len(self.meta_archs), 'invalid index of {:}'.format(index) + assert os.path.isfile(xfile_path), 'invalid data path : {:}'.format(xfile_path) + xdata = torch.load(xfile_path) + assert isinstance(xdata, dict) and 'full' in xdata and 'less' in xdata, 'invalid format of data in {:}'.format(xfile_path) + self.arch2infos_less[index] = ArchResults.create_from_state_dict( xdata['less'] ) + self.arch2infos_full[index] = ArchResults.create_from_state_dict( xdata['full'] ) + + # This function is used to query the information of a specific archiitecture + # 'arch' can be an architecture index or an architecture string + # When use_12epochs_result=True, the hyper-parameters used to train a model are in 'configs/nas-benchmark/CIFAR.config' + # When use_12epochs_result=False, the hyper-parameters used to train a model are in 'configs/nas-benchmark/LESS.config' + # The difference between these two configurations are the number of training epochs, which is 200 in CIFAR.config and 12 in LESS.config. + def query_by_arch(self, arch, use_12epochs_result=False): + if isinstance(arch, int): + arch_index = arch + else: + arch_index = self.query_index_by_arch(arch) + if arch_index == -1: return None # the following two lines are used to support few training epochs + if use_12epochs_result: arch2infos = self.arch2infos_less + else : arch2infos = self.arch2infos_full + if arch_index in arch2infos: + strings = print_information(arch2infos[ arch_index ], 'arch-index={:}'.format(arch_index)) + return '\n'.join(strings) + else: + print ('Find this arch-index : {:}, but this arch is not evaluated.'.format(arch_index)) + return None + + # This 'query_by_index' function is used to query information with the training of 12 epochs or 200 epochs. + # ------ + # If use_12epochs_result=True, we train the model by 12 epochs (see config in configs/nas-benchmark/LESS.config) + # If use_12epochs_result=False, we train the model by 200 epochs (see config in configs/nas-benchmark/CIFAR.config) + # ------ + # If dataname is None, return the ArchResults + # else, return a dict with all trials on that dataset (the key is the seed) + # Options are 'cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'. + # -- cifar10-valid : training the model on the CIFAR-10 training set. + # -- cifar10 : training the model on the CIFAR-10 training + validation set. + # -- cifar100 : training the model on the CIFAR-100 training set. + # -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + def query_by_index(self, arch_index: int, dataname: Union[None, Text] = None, + use_12epochs_result: bool = False): + if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less + else : basestr, arch2infos = '200epochs', self.arch2infos_full + assert arch_index in arch2infos, 'arch_index [{:}] does not in arch2info with {:}'.format(arch_index, basestr) + archInfo = copy.deepcopy( arch2infos[ arch_index ] ) + if dataname is None: return archInfo + else: + assert dataname in archInfo.get_dataset_names(), 'invalid dataset-name : {:}'.format(dataname) + info = archInfo.query(dataname) + return info + + def query_meta_info_by_index(self, arch_index, use_12epochs_result=False): + if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less + else : basestr, arch2infos = '200epochs', self.arch2infos_full + assert arch_index in arch2infos, 'arch_index [{:}] does not in arch2info with {:}'.format(arch_index, basestr) + archInfo = copy.deepcopy( arch2infos[ arch_index ] ) + return archInfo + + def find_best(self, dataset, metric_on_set, FLOP_max=None, Param_max=None, use_12epochs_result=False): + if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less + else : basestr, arch2infos = '200epochs', self.arch2infos_full + best_index, highest_accuracy = -1, None + for i, idx in enumerate(self.evaluated_indexes): + info = arch2infos[idx].get_compute_costs(dataset) + flop, param, latency = info['flops'], info['params'], info['latency'] + if FLOP_max is not None and flop > FLOP_max : continue + if Param_max is not None and param > Param_max: continue + xinfo = arch2infos[idx].get_metrics(dataset, metric_on_set) + loss, accuracy = xinfo['loss'], xinfo['accuracy'] + if best_index == -1: + best_index, highest_accuracy = idx, accuracy + elif highest_accuracy < accuracy: + best_index, highest_accuracy = idx, accuracy + return best_index, highest_accuracy + + + def arch(self, index: int): + """Return the topology structure of the `index`-th architecture.""" + assert 0 <= index < len(self.meta_archs), 'invalid index : {:} vs. {:}.'.format(index, len(self.meta_archs)) + return copy.deepcopy(self.meta_archs[index]) + + def get_net_param(self, index, dataset, seed, use_12epochs_result=False): + """ + This function is used to obtain the trained weights of the `index`-th architecture on `dataset` with the seed of `seed` + Args [seed]: + -- None : return a dict containing the trained weights of all trials, where each key is a seed and its corresponding value is the weights. + -- a interger : return the weights of a specific trial, whose seed is this interger. + Args [use_12epochs_result]: + -- True : train the model by 12 epochs + -- False : train the model by 200 epochs + """ + if use_12epochs_result: arch2infos = self.arch2infos_less + else: arch2infos = self.arch2infos_full + arch_result = arch2infos[index] + return arch_result.get_net_param(dataset, seed) + + + def get_net_config(self, index: int, dataset: Text): + """ + This function is used to obtain the configuration for the `index`-th architecture on `dataset`. + Args [dataset] (4 possible options): + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + This function will return a dict. + ========= Some examlpes for using this function: + config = api.get_net_config(128, 'cifar10') + """ + archresult = self.arch2infos_full[index] + all_results = archresult.query(dataset, None) + if len(all_results) == 0: raise ValueError('can not find one valid trial for the {:}-th architecture on {:}'.format(index, dataset)) + for seed, result in all_results.items(): + return result.get_config(None) + #print ('SEED [{:}] : {:}'.format(seed, result)) + raise ValueError('Impossible to reach here!') + + + def get_cost_info(self, index: int, dataset: Text, use_12epochs_result: bool = False) -> Dict[Text, float]: + """To obtain the cost metric for the `index`-th architecture on a dataset.""" + if use_12epochs_result: arch2infos = self.arch2infos_less + else: arch2infos = self.arch2infos_full + arch_result = arch2infos[index] + return arch_result.get_compute_costs(dataset) + + + def get_latency(self, index: int, dataset: Text, use_12epochs_result: bool = False) -> float: + """ + To obtain the latency of the network (by default it will return the latency with the batch size of 256). + :param index: the index of the target architecture + :param dataset: the dataset name (cifar10-valid, cifar10, cifar100, ImageNet16-120) + :return: return a float value in seconds + """ + cost_dict = self.get_cost_info(index, dataset, use_12epochs_result) + return cost_dict['latency'] + + + # obtain the metric for the `index`-th architecture + # `dataset` indicates the dataset: + # 'cifar10-valid' : using the proposed train set of CIFAR-10 as the training set + # 'cifar10' : using the proposed train+valid set of CIFAR-10 as the training set + # 'cifar100' : using the proposed train set of CIFAR-100 as the training set + # 'ImageNet16-120' : using the proposed train set of ImageNet-16-120 as the training set + # `iepoch` indicates the index of training epochs from 0 to 11/199. + # When iepoch=None, it will return the metric for the last training epoch + # When iepoch=11, it will return the metric for the 11-th training epoch (starting from 0) + # `use_12epochs_result` indicates different hyper-parameters for training + # When use_12epochs_result=True, it trains the network with 12 epochs and the LR decayed from 0.1 to 0 within 12 epochs + # When use_12epochs_result=False, it trains the network with 200 epochs and the LR decayed from 0.1 to 0 within 200 epochs + # `is_random` + # When is_random=True, the performance of a random architecture will be returned + # When is_random=False, the performanceo of all trials will be averaged. + def get_more_info(self, index: int, dataset, iepoch=None, use_12epochs_result=False, is_random=True): + if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less + else : basestr, arch2infos = '200epochs', self.arch2infos_full + archresult = arch2infos[index] + # if randomly select one trial, select the seed at first + if isinstance(is_random, bool) and is_random: + seeds = archresult.get_dataset_seeds(dataset) + is_random = random.choice(seeds) + if dataset == 'cifar10-valid': + train_info = archresult.get_metrics(dataset, 'train' , iepoch=iepoch, is_random=is_random) + valid_info = archresult.get_metrics(dataset, 'x-valid' , iepoch=iepoch, is_random=is_random) + try: + test__info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + except: + test__info = None + total = train_info['iepoch'] + 1 + xifo = {'train-loss' : train_info['loss'], + 'train-accuracy': train_info['accuracy'], + 'train-per-time': None if train_info['all_time'] is None else train_info['all_time'] / total, + 'train-all-time': train_info['all_time'], + 'valid-loss' : valid_info['loss'], + 'valid-accuracy': valid_info['accuracy'], + 'valid-all-time': valid_info['all_time'], + 'valid-per-time': None if valid_info['all_time'] is None else valid_info['all_time'] / total} + if test__info is not None: + xifo['test-loss'] = test__info['loss'] + xifo['test-accuracy'] = test__info['accuracy'] + return xifo + else: + train_info = archresult.get_metrics(dataset, 'train' , iepoch=iepoch, is_random=is_random) + try: + if dataset == 'cifar10': + test__info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + test__info = archresult.get_metrics(dataset, 'x-test', iepoch=iepoch, is_random=is_random) + except: + test__info = None + try: + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + except: + valid_info = None + try: + est_valid_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + except: + est_valid_info = None + xifo = {'train-loss' : train_info['loss'], + 'train-accuracy': train_info['accuracy']} + if test__info is not None: + xifo['test-loss'] = test__info['loss'], + xifo['test-accuracy'] = test__info['accuracy'] + if valid_info is not None: + xifo['valid-loss'] = valid_info['loss'] + xifo['valid-accuracy'] = valid_info['accuracy'] + if est_valid_info is not None: + xifo['est-valid-loss'] = est_valid_info['loss'] + xifo['est-valid-accuracy'] = est_valid_info['accuracy'] + return xifo + + + def show(self, index: int = -1): + return_flag = 0 + """ + This function will print the information of a specific (or all) architecture(s). + + :param index: If the index < 0: it will loop for all architectures and print their information one by one. + else: it will print the information of the 'index'-th archiitecture. + :return: nothing + """ + if index < 0: # show all architectures + print(self) + for i, idx in enumerate(self.evaluated_indexes): + print('\n' + '-' * 10 + ' The ({:5d}/{:5d}) {:06d}-th architecture! '.format(i, len(self.evaluated_indexes), idx) + '-'*10) + print('arch : {:}'.format(self.meta_archs[idx])) + strings = print_information(self.arch2infos_full[idx]) + print('>' * 40 + ' {:03d} epochs '.format(self.arch2infos_full[idx].get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + strings = print_information(self.arch2infos_less[idx]) + print('>' * 40 + ' {:03d} epochs '.format(self.arch2infos_less[idx].get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + print('<' * 40 + '------------' + '<' * 40) + else: + if 0 <= index < len(self.meta_archs): + if index not in self.evaluated_indexes: print('The {:}-th architecture has not been evaluated or not saved.'.format(index)) + else: + return_flag = 1 + out = [] + strings = print_information(self.arch2infos_full[index]) + out.append(strings) + print('>' * 40 + ' {:03d} epochs '.format(self.arch2infos_full[index].get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + strings = print_information(self.arch2infos_less[index]) + out.append(strings) + print('>' * 40 + ' {:03d} epochs '.format(self.arch2infos_less[index].get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + print('<' * 40 + '------------' + '<' * 40) + + else: + print('This index ({:}) is out of range (0~{:}).'.format(index, len(self.meta_archs))) + + if return_flag: + return out + + + + + + @staticmethod + def str2lists(arch_str: Text) -> List[tuple]: + """ + This function shows how to read the string-based architecture encoding. + It is the same as the `str2structure` func in `AutoDL-Projects/lib/models/cell_searchs/genotypes.py` + + :param + arch_str: the input is a string indicates the architecture topology, such as + |nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2| + :return: a list of tuple, contains multiple (op, input_node_index) pairs. + + :usage + arch = api.str2lists( '|nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2|' ) + print ('there are {:} nodes in this arch'.format(len(arch)+1)) # arch is a list + for i, node in enumerate(arch): + print('the {:}-th node is the sum of these {:} nodes with op: {:}'.format(i+1, len(node), node)) + """ + node_strs = arch_str.split('+') + genotypes = [] + for i, node_str in enumerate(node_strs): + inputs = list(filter(lambda x: x != '', node_str.split('|'))) + for xinput in inputs: assert len(xinput.split('~')) == 2, 'invalid input length : {:}'.format(xinput) + inputs = ( xi.split('~') for xi in inputs ) + input_infos = tuple( (op, int(IDX)) for (op, IDX) in inputs) + genotypes.append( input_infos ) + return genotypes + + + @staticmethod + def str2matrix(arch_str: Text, + search_space: List[Text] = ['none', 'skip_connect', 'nor_conv_1x1', 'nor_conv_3x3', 'avg_pool_3x3']) -> np.ndarray: + """ + This func shows how to convert the string-based architecture encoding to the encoding strategy in NAS-Bench-101. + + :param + arch_str: the input is a string indicates the architecture topology, such as + |nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2| + search_space: a list of operation string, the default list is the search space for NAS-Bench-201 + the default value should be be consistent with this line https://github.com/D-X-Y/AutoDL-Projects/blob/master/lib/models/cell_operations.py#L24 + :return + the numpy matrix (2-D np.ndarray) representing the DAG of this architecture topology + :usage + matrix = api.str2matrix( '|nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2|' ) + This matrix is 4-by-4 matrix representing a cell with 4 nodes (only the lower left triangle is useful). + [ [0, 0, 0, 0], # the first line represents the input (0-th) node + [2, 0, 0, 0], # the second line represents the 1-st node, is calculated by 2-th-op( 0-th-node ) + [0, 0, 0, 0], # the third line represents the 2-nd node, is calculated by 0-th-op( 0-th-node ) + 0-th-op( 1-th-node ) + [0, 0, 1, 0] ] # the fourth line represents the 3-rd node, is calculated by 0-th-op( 0-th-node ) + 0-th-op( 1-th-node ) + 1-th-op( 2-th-node ) + In NAS-Bench-201 search space, 0-th-op is 'none', 1-th-op is 'skip_connect', + 2-th-op is 'nor_conv_1x1', 3-th-op is 'nor_conv_3x3', 4-th-op is 'avg_pool_3x3'. + :(NOTE) + If a node has two input-edges from the same node, this function does not work. One edge will be overlapped. + """ + node_strs = arch_str.split('+') + num_nodes = len(node_strs) + 1 + matrix = np.zeros((num_nodes, num_nodes)) + for i, node_str in enumerate(node_strs): + inputs = list(filter(lambda x: x != '', node_str.split('|'))) + for xinput in inputs: assert len(xinput.split('~')) == 2, 'invalid input length : {:}'.format(xinput) + for xi in inputs: + op, idx = xi.split('~') + if op not in search_space: raise ValueError('this op ({:}) is not in {:}'.format(op, search_space)) + op_idx, node_idx = search_space.index(op), int(idx) + matrix[i+1, node_idx] = op_idx + return matrix + + + +class ArchResults(object): + + def __init__(self, arch_index, arch_str): + self.arch_index = int(arch_index) + self.arch_str = copy.deepcopy(arch_str) + self.all_results = dict() + self.dataset_seed = dict() + self.clear_net_done = False + + def get_compute_costs(self, dataset): + x_seeds = self.dataset_seed[dataset] + results = [self.all_results[ (dataset, seed) ] for seed in x_seeds] + + flops = [result.flop for result in results] + params = [result.params for result in results] + latencies = [result.get_latency() for result in results] + latencies = [x for x in latencies if x > 0] + mean_latency = np.mean(latencies) if len(latencies) > 0 else None + time_infos = defaultdict(list) + for result in results: + time_info = result.get_times() + for key, value in time_info.items(): time_infos[key].append( value ) + + info = {'flops' : np.mean(flops), + 'params' : np.mean(params), + 'latency': mean_latency} + for key, value in time_infos.items(): + if len(value) > 0 and value[0] is not None: + info[key] = np.mean(value) + else: info[key] = None + return info + + def get_metrics(self, dataset, setname, iepoch=None, is_random=False): + """ + This `get_metrics` function is used to obtain obtain the loss, accuracy, etc information on a specific dataset. + If not specify, each set refer to the proposed split in NAS-Bench-201 paper. + If some args return None or raise error, then it is not avaliable. + ======================================== + Args [dataset] (4 possible options): + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + Args [setname] (each dataset has different setnames): + -- When dataset = cifar10-valid, you can use 'train', 'x-valid', 'ori-test' + ------ 'train' : the metric on the training set. + ------ 'x-valid' : the metric on the validation set. + ------ 'ori-test' : the metric on the test set. + -- When dataset = cifar10, you can use 'train', 'ori-test'. + ------ 'train' : the metric on the training + validation set. + ------ 'ori-test' : the metric on the test set. + -- When dataset = cifar100 or ImageNet16-120, you can use 'train', 'ori-test', 'x-valid', 'x-test' + ------ 'train' : the metric on the training set. + ------ 'x-valid' : the metric on the validation set. + ------ 'x-test' : the metric on the test set. + ------ 'ori-test' : the metric on the validation + test set. + Args [iepoch] (None or an integer in [0, the-number-of-total-training-epochs) + ------ None : return the metric after the last training epoch. + ------ an integer i : return the metric after the i-th training epoch. + Args [is_random]: + ------ True : return the metric of a randomly selected trial. + ------ False : return the averaged metric of all avaliable trials. + ------ an integer indicating the 'seed' value : return the metric of a specific trial (whose random seed is 'is_random'). + """ + x_seeds = self.dataset_seed[dataset] + results = [self.all_results[ (dataset, seed) ] for seed in x_seeds] + infos = defaultdict(list) + for result in results: + if setname == 'train': + info = result.get_train(iepoch) + else: + info = result.get_eval(setname, iepoch) + for key, value in info.items(): infos[key].append( value ) + return_info = dict() + if isinstance(is_random, bool) and is_random: # randomly select one + index = random.randint(0, len(results)-1) + for key, value in infos.items(): return_info[key] = value[index] + elif isinstance(is_random, bool) and not is_random: # average + for key, value in infos.items(): + if len(value) > 0 and value[0] is not None: + return_info[key] = np.mean(value) + else: return_info[key] = None + elif isinstance(is_random, int): # specify the seed + if is_random not in x_seeds: raise ValueError('can not find random seed ({:}) from {:}'.format(is_random, x_seeds)) + index = x_seeds.index(is_random) + for key, value in infos.items(): return_info[key] = value[index] + else: + raise ValueError('invalid value for is_random: {:}'.format(is_random)) + return return_info + + def show(self, is_print=False): + return print_information(self, None, is_print) + + def get_dataset_names(self): + return list(self.dataset_seed.keys()) + + def get_dataset_seeds(self, dataset): + return copy.deepcopy( self.dataset_seed[dataset] ) + + def get_net_param(self, dataset: Text, seed: Union[None, int] =None): + """ + This function will return the trained network's weights on the 'dataset'. + :arg + dataset: one of 'cifar10-valid', 'cifar10', 'cifar100', and 'ImageNet16-120'. + seed: an integer indicates the seed value or None that indicates returing all trials. + """ + if seed is None: + x_seeds = self.dataset_seed[dataset] + return {seed: self.all_results[(dataset, seed)].get_net_param() for seed in x_seeds} + else: + return self.all_results[(dataset, seed)].get_net_param() + + def reset_latency(self, dataset: Text, seed: Union[None, Text], latency: float) -> None: + """This function is used to reset the latency in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].update_latency([latency]) + else: + self.all_results[(dataset, seed)].update_latency([latency]) + + def reset_pseudo_train_times(self, dataset: Text, seed: Union[None, Text], estimated_per_epoch_time: float) -> None: + """This function is used to reset the train-times in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].reset_pseudo_train_times(estimated_per_epoch_time) + else: + self.all_results[(dataset, seed)].reset_pseudo_train_times(estimated_per_epoch_time) + + def reset_pseudo_eval_times(self, dataset: Text, seed: Union[None, Text], eval_name: Text, estimated_per_epoch_time: float) -> None: + """This function is used to reset the eval-times in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].reset_pseudo_eval_times(eval_name, estimated_per_epoch_time) + else: + self.all_results[(dataset, seed)].reset_pseudo_eval_times(eval_name, estimated_per_epoch_time) + + def get_latency(self, dataset: Text) -> float: + """Get the latency of a model on the target dataset. [Timestamp: 2020.03.09]""" + latencies = [] + for seed in self.dataset_seed[dataset]: + latency = self.all_results[(dataset, seed)].get_latency() + if not isinstance(latency, float) or latency <= 0: + raise ValueError('invalid latency of {:} for {:} with {:}'.format(dataset)) + latencies.append(latency) + return sum(latencies) / len(latencies) + + def get_total_epoch(self, dataset=None): + """Return the total number of training epochs.""" + if dataset is None: + epochss = [] + for xdata, x_seeds in self.dataset_seed.items(): + epochss += [self.all_results[(xdata, seed)].get_total_epoch() for seed in x_seeds] + elif isinstance(dataset, str): + x_seeds = self.dataset_seed[dataset] + epochss = [self.all_results[(dataset, seed)].get_total_epoch() for seed in x_seeds] + else: + raise ValueError('invalid dataset={:}'.format(dataset)) + if len(set(epochss)) > 1: raise ValueError('Each trial mush have the same number of training epochs : {:}'.format(epochss)) + return epochss[-1] + + def query(self, dataset, seed=None): + """Return the ResultsCount object (containing all information of a single trial) for 'dataset' and 'seed'""" + if seed is None: + x_seeds = self.dataset_seed[dataset] + return {seed: self.all_results[(dataset, seed)] for seed in x_seeds} + else: + return self.all_results[(dataset, seed)] + + def arch_idx_str(self): + return '{:06d}'.format(self.arch_index) + + def update(self, dataset_name, seed, result): + if dataset_name not in self.dataset_seed: + self.dataset_seed[dataset_name] = [] + assert seed not in self.dataset_seed[dataset_name], '{:}-th arch alreadly has this seed ({:}) on {:}'.format(self.arch_index, seed, dataset_name) + self.dataset_seed[ dataset_name ].append( seed ) + self.dataset_seed[ dataset_name ] = sorted( self.dataset_seed[ dataset_name ] ) + assert (dataset_name, seed) not in self.all_results + self.all_results[ (dataset_name, seed) ] = result + self.clear_net_done = False + + def state_dict(self): + state_dict = dict() + for key, value in self.__dict__.items(): + if key == 'all_results': # contain the class of ResultsCount + xvalue = dict() + assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value)) + for _k, _v in value.items(): + assert isinstance(_v, ResultsCount), 'invalid type of value for {:}/{:} : {:}'.format(key, _k, type(_v)) + xvalue[_k] = _v.state_dict() + else: + xvalue = value + state_dict[key] = xvalue + return state_dict + + def load_state_dict(self, state_dict): + new_state_dict = dict() + for key, value in state_dict.items(): + if key == 'all_results': # to convert to the class of ResultsCount + xvalue = dict() + assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value)) + for _k, _v in value.items(): + xvalue[_k] = ResultsCount.create_from_state_dict(_v) + else: xvalue = value + new_state_dict[key] = xvalue + self.__dict__.update(new_state_dict) + + @staticmethod + def create_from_state_dict(state_dict_or_file): + x = ArchResults(-1, -1) + if isinstance(state_dict_or_file, str): # a file path + state_dict = torch.load(state_dict_or_file) + elif isinstance(state_dict_or_file, dict): + state_dict = state_dict_or_file + else: + raise ValueError('invalid type of state_dict_or_file : {:}'.format(type(state_dict_or_file))) + x.load_state_dict(state_dict) + return x + + # This function is used to clear the weights saved in each 'result' + # This can help reduce the memory footprint. + def clear_params(self): + for key, result in self.all_results.items(): + result.net_state_dict = None + self.clear_net_done = True + + def debug_test(self): + """This function is used for me to debug and test, which will call most methods.""" + all_dataset = ['cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'] + for dataset in all_dataset: + print('---->>>> {:}'.format(dataset)) + print('The latency on {:} is {:} s'.format(dataset, self.get_latency(dataset))) + for seed in self.dataset_seed[dataset]: + result = self.all_results[(dataset, seed)] + print(' ==>> result = {:}'.format(result)) + print(' ==>> cost = {:}'.format(result.get_times())) + + def __repr__(self): + return ('{name}(arch-index={index}, arch={arch}, {num} runs, clear={clear})'.format(name=self.__class__.__name__, index=self.arch_index, arch=self.arch_str, num=len(self.all_results), clear=self.clear_net_done)) + + + +""" +This class (ResultsCount) is used to save the information of one trial for a single architecture. +I did not write much comment for this class, because it is the lowest-level class in NAS-Bench-201 API, which will be rarely called. +If you have any question regarding this class, please open an issue or email me. +""" +class ResultsCount(object): + + def __init__(self, name, state_dict, train_accs, train_losses, params, flop, arch_config, seed, epochs, latency): + self.name = name + self.net_state_dict = state_dict + self.train_acc1es = copy.deepcopy(train_accs) + self.train_acc5es = None + self.train_losses = copy.deepcopy(train_losses) + self.train_times = None + self.arch_config = copy.deepcopy(arch_config) + self.params = params + self.flop = flop + self.seed = seed + self.epochs = epochs + self.latency = latency + # evaluation results + self.reset_eval() + + def update_train_info(self, train_acc1es, train_acc5es, train_losses, train_times) -> None: + self.train_acc1es = train_acc1es + self.train_acc5es = train_acc5es + self.train_losses = train_losses + self.train_times = train_times + + def reset_pseudo_train_times(self, estimated_per_epoch_time: float) -> None: + """Assign the training times.""" + train_times = OrderedDict() + for i in range(self.epochs): + train_times[i] = estimated_per_epoch_time + self.train_times = train_times + + def reset_pseudo_eval_times(self, eval_name: Text, estimated_per_epoch_time: float) -> None: + """Assign the evaluation times.""" + if eval_name not in self.eval_names: raise ValueError('invalid eval name : {:}'.format(eval_name)) + for i in range(self.epochs): + self.eval_times['{:}@{:}'.format(eval_name,i)] = estimated_per_epoch_time + + def reset_eval(self): + self.eval_names = [] + self.eval_acc1es = {} + self.eval_times = {} + self.eval_losses = {} + + def update_latency(self, latency): + self.latency = copy.deepcopy( latency ) + + def get_latency(self) -> float: + """Return the latency value in seconds. -1 represents not avaliable ; otherwise it should be a float value""" + if self.latency is None: return -1.0 + else: return sum(self.latency) / len(self.latency) + + def update_eval(self, accs, losses, times): # new version + data_names = set([x.split('@')[0] for x in accs.keys()]) + for data_name in data_names: + assert data_name not in self.eval_names, '{:} has already been added into eval-names'.format(data_name) + self.eval_names.append( data_name ) + for iepoch in range(self.epochs): + xkey = '{:}@{:}'.format(data_name, iepoch) + self.eval_acc1es[ xkey ] = accs[ xkey ] + self.eval_losses[ xkey ] = losses[ xkey ] + self.eval_times [ xkey ] = times[ xkey ] + + def update_OLD_eval(self, name, accs, losses): # old version + assert name not in self.eval_names, '{:} has already added'.format(name) + self.eval_names.append( name ) + for iepoch in range(self.epochs): + if iepoch in accs: + self.eval_acc1es['{:}@{:}'.format(name,iepoch)] = accs[iepoch] + self.eval_losses['{:}@{:}'.format(name,iepoch)] = losses[iepoch] + + def __repr__(self): + num_eval = len(self.eval_names) + set_name = '[' + ', '.join(self.eval_names) + ']' + return ('{name}({xname}, arch={arch}, FLOP={flop:.2f}M, Param={param:.3f}MB, seed={seed}, {num_eval} eval-sets: {set_name})'.format(name=self.__class__.__name__, xname=self.name, arch=self.arch_config['arch_str'], flop=self.flop, param=self.params, seed=self.seed, num_eval=num_eval, set_name=set_name)) + + def get_total_epoch(self): + return copy.deepcopy(self.epochs) + + def get_times(self): + """Obtain the information regarding both training and evaluation time.""" + if self.train_times is not None and isinstance(self.train_times, dict): + train_times = list( self.train_times.values() ) + time_info = {'T-train@epoch': np.mean(train_times), 'T-train@total': np.sum(train_times)} + else: + time_info = {'T-train@epoch': None, 'T-train@total': None } + for name in self.eval_names: + try: + xtimes = [self.eval_times['{:}@{:}'.format(name,i)] for i in range(self.epochs)] + time_info['T-{:}@epoch'.format(name)] = np.mean(xtimes) + time_info['T-{:}@total'.format(name)] = np.sum(xtimes) + except: + time_info['T-{:}@epoch'.format(name)] = None + time_info['T-{:}@total'.format(name)] = None + return time_info + + def get_eval_set(self): + return self.eval_names + + # get the training information + def get_train(self, iepoch=None): + if iepoch is None: iepoch = self.epochs-1 + assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs) + if self.train_times is not None: + xtime = self.train_times[iepoch] + atime = sum([self.train_times[i] for i in range(iepoch+1)]) + else: xtime, atime = None, None + return {'iepoch' : iepoch, + 'loss' : self.train_losses[iepoch], + 'accuracy': self.train_acc1es[iepoch], + 'cur_time': xtime, + 'all_time': atime} + + # get the evaluation information ; there could be multiple evaluation sets (identified by the 'name' argument). + def get_eval(self, name, iepoch=None): + if iepoch is None: iepoch = self.epochs-1 + assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs) + if isinstance(self.eval_times,dict) and len(self.eval_times) > 0: + xtime = self.eval_times['{:}@{:}'.format(name,iepoch)] + atime = sum([self.eval_times['{:}@{:}'.format(name,i)] for i in range(iepoch+1)]) + else: xtime, atime = None, None + return {'iepoch' : iepoch, + 'loss' : self.eval_losses['{:}@{:}'.format(name,iepoch)], + 'accuracy': self.eval_acc1es['{:}@{:}'.format(name,iepoch)], + 'cur_time': xtime, + 'all_time': atime} + + def get_net_param(self, clone=False): + if clone: return copy.deepcopy(self.net_state_dict) + else: return self.net_state_dict + + # This function is used to obtain the config dict for this architecture. + def get_config(self, str2structure): + if str2structure is None: + return {'name': 'infer.tiny', 'C': self.arch_config['channel'], + 'N' : self.arch_config['num_cells'], + 'arch_str': self.arch_config['arch_str'], 'num_classes': self.arch_config['class_num']} + else: + return {'name': 'infer.tiny', 'C': self.arch_config['channel'], + 'N' : self.arch_config['num_cells'], + 'genotype': str2structure(self.arch_config['arch_str']), 'num_classes': self.arch_config['class_num']} + + def state_dict(self): + _state_dict = {key: value for key, value in self.__dict__.items()} + return _state_dict + + def load_state_dict(self, state_dict): + self.__dict__.update(state_dict) + + @staticmethod + def create_from_state_dict(state_dict): + x = ResultsCount(None, None, None, None, None, None, None, None, None, None) + x.load_state_dict(state_dict) + return x diff --git a/nas_201_api/api_201.py b/nas_201_api/api_201.py new file mode 100644 index 0000000..8c995c9 --- /dev/null +++ b/nas_201_api/api_201.py @@ -0,0 +1,274 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +############################################################################################ +# NAS-Bench-201: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 # +############################################################################################ +# The history of benchmark files: +# [2020.02.25] NAS-Bench-201-v1_0-e61699.pth : 6219 architectures are trained once, 1621 architectures are trained twice, 7785 architectures are trained three times. `LESS` only supports CIFAR10-VALID. +# [2020.03.16] NAS-Bench-201-v1_1-096897.pth : 2225 architectures are trained once, 5439 archiitectures are trained twice, 7961 architectures are trained three times on all training sets. For the hyper-parameters with the total epochs of 12, each model is trained on CIFAR-10, CIFAR-100, ImageNet16-120 once, and is trained on CIFAR-10-VALID twice. +# +# I'm still actively enhancing our benchmark, while for the future benchmark file, please follow news from NATS-Bench (an extended version of NAS-Bench-201). +# +import os, copy, random, torch, numpy as np +from pathlib import Path +from typing import List, Text, Union, Dict, Optional +from collections import OrderedDict, defaultdict + +from .api_utils import ArchResults +from .api_utils import NASBenchMetaAPI +from .api_utils import remap_dataset_set_names + + +ALL_BENCHMARK_FILES = ['NAS-Bench-201-v1_0-e61699.pth', 'NAS-Bench-201-v1_1-096897.pth'] +ALL_ARCHIVE_DIRS = ['NAS-Bench-201-v1_1-archive'] + + +def print_information(information, extra_info=None, show=False): + dataset_names = information.get_dataset_names() + strings = [information.arch_str, 'datasets : {:}, extra-info : {:}'.format(dataset_names, extra_info)] + def metric2str(loss, acc): + return 'loss = {:.3f}, top1 = {:.2f}%'.format(loss, acc) + + for ida, dataset in enumerate(dataset_names): + metric = information.get_compute_costs(dataset) + flop, param, latency = metric['flops'], metric['params'], metric['latency'] + str1 = '{:14s} FLOP={:6.2f} M, Params={:.3f} MB, latency={:} ms.'.format(dataset, flop, param, '{:.2f}'.format(latency*1000) if latency is not None and latency > 0 else None) + train_info = information.get_metrics(dataset, 'train') + if dataset == 'cifar10-valid': + valid_info = information.get_metrics(dataset, 'x-valid') + str2 = '{:14s} train : [{:}], valid : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy'])) + elif dataset == 'cifar10': + test__info = information.get_metrics(dataset, 'ori-test') + str2 = '{:14s} train : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + else: + valid_info = information.get_metrics(dataset, 'x-valid') + test__info = information.get_metrics(dataset, 'x-test') + str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy'])) + strings += [str1, str2] + if show: print('\n'.join(strings)) + return strings + + +""" +This is the class for the API of NAS-Bench-201. +""" +class NASBench201API(NASBenchMetaAPI): + + """ The initialization function that takes the dataset file path (or a dict loaded from that path) as input. """ + def __init__(self, file_path_or_dict: Optional[Union[Text, Dict]]=None, + verbose: bool=True): + self.filename = None + self.reset_time() + if file_path_or_dict is None: + file_path_or_dict = os.path.join(os.environ['TORCH_HOME'], ALL_BENCHMARK_FILES[-1]) + print ('Try to use the default NAS-Bench-201 path from {:}.'.format(file_path_or_dict)) + if isinstance(file_path_or_dict, str) or isinstance(file_path_or_dict, Path): + file_path_or_dict = str(file_path_or_dict) + if verbose: print('try to create the NAS-Bench-201 api from {:}'.format(file_path_or_dict)) + assert os.path.isfile(file_path_or_dict), 'invalid path : {:}'.format(file_path_or_dict) + self.filename = Path(file_path_or_dict).name + file_path_or_dict = torch.load(file_path_or_dict, map_location='cpu') + elif isinstance(file_path_or_dict, dict): + file_path_or_dict = copy.deepcopy(file_path_or_dict) + else: raise ValueError('invalid type : {:} not in [str, dict]'.format(type(file_path_or_dict))) + assert isinstance(file_path_or_dict, dict), 'It should be a dict instead of {:}'.format(type(file_path_or_dict)) + self.verbose = verbose # [TODO] a flag indicating whether to print more logs + keys = ('meta_archs', 'arch2infos', 'evaluated_indexes') + for key in keys: assert key in file_path_or_dict, 'Can not find key[{:}] in the dict'.format(key) + self.meta_archs = copy.deepcopy( file_path_or_dict['meta_archs'] ) + # This is a dict mapping each architecture to a dict, where the key is #epochs and the value is ArchResults + self.arch2infos_dict = OrderedDict() + self._avaliable_hps = set(['12', '200']) + for xkey in sorted(list(file_path_or_dict['arch2infos'].keys())): + all_info = file_path_or_dict['arch2infos'][xkey] + hp2archres = OrderedDict() + # self.arch2infos_less[xkey] = ArchResults.create_from_state_dict( all_info['less'] ) + # self.arch2infos_full[xkey] = ArchResults.create_from_state_dict( all_info['full'] ) + hp2archres['12'] = ArchResults.create_from_state_dict(all_info['less']) + hp2archres['200'] = ArchResults.create_from_state_dict(all_info['full']) + self.arch2infos_dict[xkey] = hp2archres + self.evaluated_indexes = sorted(list(file_path_or_dict['evaluated_indexes'])) + self.archstr2index = {} + for idx, arch in enumerate(self.meta_archs): + assert arch not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch]) + self.archstr2index[ arch ] = idx + + def reload(self, archive_root: Text = None, index: int = None): + """Overwrite all information of the 'index'-th architecture in the search space. + It will load its data from 'archive_root'. + """ + if archive_root is None: + archive_root = os.path.join(os.environ['TORCH_HOME'], ALL_ARCHIVE_DIRS[-1]) + assert os.path.isdir(archive_root), 'invalid directory : {:}'.format(archive_root) + if index is None: + indexes = list(range(len(self))) + else: + indexes = [index] + for idx in indexes: + assert 0 <= idx < len(self.meta_archs), 'invalid index of {:}'.format(idx) + xfile_path = os.path.join(archive_root, '{:06d}-FULL.pth'.format(idx)) + assert os.path.isfile(xfile_path), 'invalid data path : {:}'.format(xfile_path) + xdata = torch.load(xfile_path, map_location='cpu') + assert isinstance(xdata, dict) and 'full' in xdata and 'less' in xdata, 'invalid format of data in {:}'.format(xfile_path) + hp2archres = OrderedDict() + hp2archres['12'] = ArchResults.create_from_state_dict(xdata['less']) + hp2archres['200'] = ArchResults.create_from_state_dict(xdata['full']) + self.arch2infos_dict[idx] = hp2archres + + def query_info_str_by_arch(self, arch, hp: Text='12'): + """ This function is used to query the information of a specific architecture + 'arch' can be an architecture index or an architecture string + When hp=12, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/12E.config' + When hp=200, the hyper-parameters used to train a model are in 'configs/nas-benchmark/hyper-opts/200E.config' + The difference between these three configurations are the number of training epochs. + """ + if self.verbose: + print('Call query_info_str_by_arch with arch={:} and hp={:}'.format(arch, hp)) + return self._query_info_str_by_arch(arch, hp, print_information) + + # obtain the metric for the `index`-th architecture + # `dataset` indicates the dataset: + # 'cifar10-valid' : using the proposed train set of CIFAR-10 as the training set + # 'cifar10' : using the proposed train+valid set of CIFAR-10 as the training set + # 'cifar100' : using the proposed train set of CIFAR-100 as the training set + # 'ImageNet16-120' : using the proposed train set of ImageNet-16-120 as the training set + # `iepoch` indicates the index of training epochs from 0 to 11/199. + # When iepoch=None, it will return the metric for the last training epoch + # When iepoch=11, it will return the metric for the 11-th training epoch (starting from 0) + # `use_12epochs_result` indicates different hyper-parameters for training + # When use_12epochs_result=True, it trains the network with 12 epochs and the LR decayed from 0.1 to 0 within 12 epochs + # When use_12epochs_result=False, it trains the network with 200 epochs and the LR decayed from 0.1 to 0 within 200 epochs + # `is_random` + # When is_random=True, the performance of a random architecture will be returned + # When is_random=False, the performanceo of all trials will be averaged. + def get_more_info(self, index, dataset, iepoch=None, hp='12', is_random=True): + if self.verbose: + print('Call the get_more_info function with index={:}, dataset={:}, iepoch={:}, hp={:}, and is_random={:}.'.format(index, dataset, iepoch, hp, is_random)) + index = self.query_index_by_arch(index) # To avoid the input is a string or an instance of a arch object + if index not in self.arch2infos_dict: + raise ValueError('Did not find {:} from arch2infos_dict.'.format(index)) + archresult = self.arch2infos_dict[index][str(hp)] + # if randomly select one trial, select the seed at first + if isinstance(is_random, bool) and is_random: + seeds = archresult.get_dataset_seeds(dataset) + is_random = random.choice(seeds) + # collect the training information + train_info = archresult.get_metrics(dataset, 'train', iepoch=iepoch, is_random=is_random) + total = train_info['iepoch'] + 1 + xinfo = {'train-loss' : train_info['loss'], + 'train-accuracy': train_info['accuracy'], + 'train-per-time': train_info['all_time'] / total if train_info['all_time'] is not None else None, + 'train-all-time': train_info['all_time']} + # collect the evaluation information + if dataset == 'cifar10-valid': + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + try: + test_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + except: + test_info = None + valtest_info = None + else: + try: # collect results on the proposed test set + if dataset == 'cifar10': + test_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + test_info = archresult.get_metrics(dataset, 'x-test', iepoch=iepoch, is_random=is_random) + except: + test_info = None + try: # collect results on the proposed validation set + valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random) + except: + valid_info = None + try: + if dataset != 'cifar10': + valtest_info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random) + else: + valtest_info = None + except: + valtest_info = None + if valid_info is not None: + xinfo['valid-loss'] = valid_info['loss'] + xinfo['valid-accuracy'] = valid_info['accuracy'] + xinfo['valid-per-time'] = valid_info['all_time'] / total if valid_info['all_time'] is not None else None + xinfo['valid-all-time'] = valid_info['all_time'] + if test_info is not None: + xinfo['test-loss'] = test_info['loss'] + xinfo['test-accuracy'] = test_info['accuracy'] + xinfo['test-per-time'] = test_info['all_time'] / total if test_info['all_time'] is not None else None + xinfo['test-all-time'] = test_info['all_time'] + if valtest_info is not None: + xinfo['valtest-loss'] = valtest_info['loss'] + xinfo['valtest-accuracy'] = valtest_info['accuracy'] + xinfo['valtest-per-time'] = valtest_info['all_time'] / total if valtest_info['all_time'] is not None else None + xinfo['valtest-all-time'] = valtest_info['all_time'] + return xinfo + + def show(self, index: int = -1) -> None: + """This function will print the information of a specific (or all) architecture(s).""" + self._show(index, print_information) + + @staticmethod + def str2lists(arch_str: Text) -> List[tuple]: + """ + This function shows how to read the string-based architecture encoding. + It is the same as the `str2structure` func in `AutoDL-Projects/lib/models/cell_searchs/genotypes.py` + + :param + arch_str: the input is a string indicates the architecture topology, such as + |nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2| + :return: a list of tuple, contains multiple (op, input_node_index) pairs. + + :usage + arch = api.str2lists( '|nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2|' ) + print ('there are {:} nodes in this arch'.format(len(arch)+1)) # arch is a list + for i, node in enumerate(arch): + print('the {:}-th node is the sum of these {:} nodes with op: {:}'.format(i+1, len(node), node)) + """ + node_strs = arch_str.split('+') + genotypes = [] + for i, node_str in enumerate(node_strs): + inputs = list(filter(lambda x: x != '', node_str.split('|'))) + for xinput in inputs: assert len(xinput.split('~')) == 2, 'invalid input length : {:}'.format(xinput) + inputs = ( xi.split('~') for xi in inputs ) + input_infos = tuple( (op, int(IDX)) for (op, IDX) in inputs) + genotypes.append( input_infos ) + return genotypes + + @staticmethod + def str2matrix(arch_str: Text, + search_space: List[Text] = ['none', 'skip_connect', 'nor_conv_1x1', 'nor_conv_3x3', 'avg_pool_3x3']) -> np.ndarray: + """ + This func shows how to convert the string-based architecture encoding to the encoding strategy in NAS-Bench-101. + + :param + arch_str: the input is a string indicates the architecture topology, such as + |nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2| + search_space: a list of operation string, the default list is the search space for NAS-Bench-201 + the default value should be be consistent with this line https://github.com/D-X-Y/AutoDL-Projects/blob/master/lib/models/cell_operations.py#L24 + :return + the numpy matrix (2-D np.ndarray) representing the DAG of this architecture topology + :usage + matrix = api.str2matrix( '|nor_conv_1x1~0|+|none~0|none~1|+|none~0|none~1|skip_connect~2|' ) + This matrix is 4-by-4 matrix representing a cell with 4 nodes (only the lower left triangle is useful). + [ [0, 0, 0, 0], # the first line represents the input (0-th) node + [2, 0, 0, 0], # the second line represents the 1-st node, is calculated by 2-th-op( 0-th-node ) + [0, 0, 0, 0], # the third line represents the 2-nd node, is calculated by 0-th-op( 0-th-node ) + 0-th-op( 1-th-node ) + [0, 0, 1, 0] ] # the fourth line represents the 3-rd node, is calculated by 0-th-op( 0-th-node ) + 0-th-op( 1-th-node ) + 1-th-op( 2-th-node ) + In NAS-Bench-201 search space, 0-th-op is 'none', 1-th-op is 'skip_connect', + 2-th-op is 'nor_conv_1x1', 3-th-op is 'nor_conv_3x3', 4-th-op is 'avg_pool_3x3'. + :(NOTE) + If a node has two input-edges from the same node, this function does not work. One edge will be overlapped. + """ + node_strs = arch_str.split('+') + num_nodes = len(node_strs) + 1 + matrix = np.zeros((num_nodes, num_nodes)) + for i, node_str in enumerate(node_strs): + inputs = list(filter(lambda x: x != '', node_str.split('|'))) + for xinput in inputs: assert len(xinput.split('~')) == 2, 'invalid input length : {:}'.format(xinput) + for xi in inputs: + op, idx = xi.split('~') + if op not in search_space: raise ValueError('this op ({:}) is not in {:}'.format(op, search_space)) + op_idx, node_idx = search_space.index(op), int(idx) + matrix[i+1, node_idx] = op_idx + return matrix + diff --git a/nas_201_api/api_utils.py b/nas_201_api/api_utils.py new file mode 100644 index 0000000..0989472 --- /dev/null +++ b/nas_201_api/api_utils.py @@ -0,0 +1,750 @@ +##################################################### +# Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2019.08 # +############################################################################################ +# NAS-Bench-201: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 # +############################################################################################ +# In this Python file, we define NASBenchMetaAPI, the abstract class for benchmark APIs. +# We also define the class ArchResults, which contains all information of a single architecture trained by one kind of hyper-parameters on three datasets. +# We also define the class ResultsCount, which contains all information of a single trial for a single architecture. +############################################################################################ +# +import os, abc, copy, random, torch, numpy as np +from pathlib import Path +from typing import List, Text, Union, Dict, Optional +from collections import OrderedDict, defaultdict + + +def remap_dataset_set_names(dataset, metric_on_set, verbose=False): + """re-map the metric_on_set to internal keys""" + if verbose: + print('Call internal function _remap_dataset_set_names with dataset={:} and metric_on_set={:}'.format(dataset, metric_on_set)) + if dataset == 'cifar10' and metric_on_set == 'valid': + dataset, metric_on_set = 'cifar10-valid', 'x-valid' + elif dataset == 'cifar10' and metric_on_set == 'test': + dataset, metric_on_set = 'cifar10', 'ori-test' + elif dataset == 'cifar10' and metric_on_set == 'train': + dataset, metric_on_set = 'cifar10', 'train' + elif (dataset == 'cifar100' or dataset == 'ImageNet16-120') and metric_on_set == 'valid': + metric_on_set = 'x-valid' + elif (dataset == 'cifar100' or dataset == 'ImageNet16-120') and metric_on_set == 'test': + metric_on_set = 'x-test' + if verbose: + print(' return dataset={:} and metric_on_set={:}'.format(dataset, metric_on_set)) + return dataset, metric_on_set + + +class NASBenchMetaAPI(metaclass=abc.ABCMeta): + + @abc.abstractmethod + def __init__(self, file_path_or_dict: Optional[Union[Text, Dict]]=None, verbose: bool=True): + """The initialization function that takes the dataset file path (or a dict loaded from that path) as input.""" + + def __getitem__(self, index: int): + return copy.deepcopy(self.meta_archs[index]) + + def arch(self, index: int): + """Return the topology structure of the `index`-th architecture.""" + if self.verbose: + print('Call the arch function with index={:}'.format(index)) + assert 0 <= index < len(self.meta_archs), 'invalid index : {:} vs. {:}.'.format(index, len(self.meta_archs)) + return copy.deepcopy(self.meta_archs[index]) + + def __len__(self): + return len(self.meta_archs) + + def __repr__(self): + return ('{name}({num}/{total} architectures, file={filename})'.format(name=self.__class__.__name__, num=len(self.evaluated_indexes), total=len(self.meta_archs), filename=self.filename)) + + @property + def avaliable_hps(self): + return list(copy.deepcopy(self._avaliable_hps)) + + @property + def used_time(self): + return self._used_time + + def reset_time(self): + self._used_time = 0 + + def simulate_train_eval(self, arch, dataset, iepoch=None, hp='12', account_time=True): + index = self.query_index_by_arch(arch) + all_names = ('cifar10', 'cifar100', 'ImageNet16-120') + assert dataset in all_names, 'Invalid dataset name : {:} vs {:}'.format(dataset, all_names) + if dataset == 'cifar10': + info = self.get_more_info(index, 'cifar10-valid', iepoch=iepoch, hp=hp, is_random=True) + else: + info = self.get_more_info(index, dataset, iepoch=iepoch, hp=hp, is_random=True) + valid_acc, time_cost = info['valid-accuracy'], info['train-all-time'] + info['valid-per-time'] + latency = self.get_latency(index, dataset) + if account_time: + self._used_time += time_cost + return valid_acc, latency, time_cost, self._used_time + + def random(self): + """Return a random index of all architectures.""" + return random.randint(0, len(self.meta_archs)-1) + + def query_index_by_arch(self, arch): + """ This function is used to query the index of an architecture in the search space. + In the topology search space, the input arch can be an architecture string such as '|nor_conv_3x3~0|+|nor_conv_3x3~0|avg_pool_3x3~1|+|skip_connect~0|nor_conv_3x3~1|skip_connect~2|'; + or an instance that has the 'tostr' function that can generate the architecture string; + or it is directly an architecture index, in this case, we will check whether it is valid or not. + This function will return the index. + If return -1, it means this architecture is not in the search space. + Otherwise, it will return an int in [0, the-number-of-candidates-in-the-search-space). + """ + if self.verbose: + print('Call query_index_by_arch with arch={:}'.format(arch)) + if isinstance(arch, int): + if 0 <= arch < len(self): + return arch + else: + raise ValueError('Invalid architecture index {:} vs [{:}, {:}].'.format(arch, 0, len(self))) + elif isinstance(arch, str): + if arch in self.archstr2index: arch_index = self.archstr2index[ arch ] + else : arch_index = -1 + elif hasattr(arch, 'tostr'): + if arch.tostr() in self.archstr2index: arch_index = self.archstr2index[ arch.tostr() ] + else : arch_index = -1 + else: arch_index = -1 + return arch_index + + def query_by_arch(self, arch, hp): + # This is to make the current version be compatible with the old version. + return self.query_info_str_by_arch(arch, hp) + + @abc.abstractmethod + def reload(self, archive_root: Text = None, index: int = None): + """Overwrite all information of the 'index'-th architecture in the search space, where the data will be loaded from 'archive_root'. + If index is None, overwrite all ckps. + """ + + def clear_params(self, index: int, hp: Optional[Text]=None): + """Remove the architecture's weights to save memory. + :arg + index: the index of the target architecture + hp: a flag to controll how to clear the parameters. + -- None: clear all the weights in '01'/'12'/'90', which indicates the number of training epochs. + -- '01' or '12' or '90': clear all the weights in arch2infos_dict[index][hp]. + """ + if self.verbose: + print('Call clear_params with index={:} and hp={:}'.format(index, hp)) + if hp is None: + for key, result in self.arch2infos_dict[index].items(): + result.clear_params() + else: + if str(hp) not in self.arch2infos_dict[index]: + raise ValueError('The {:}-th architecture only has hyper-parameters of {:} instead of {:}.'.format(index, list(self.arch2infos_dict[index].keys()), hp)) + self.arch2infos_dict[index][str(hp)].clear_params() + + @abc.abstractmethod + def query_info_str_by_arch(self, arch, hp: Text='12'): + """This function is used to query the information of a specific architecture.""" + + def _query_info_str_by_arch(self, arch, hp: Text='12', print_information=None): + arch_index = self.query_index_by_arch(arch) + if arch_index in self.arch2infos_dict: + if hp not in self.arch2infos_dict[arch_index]: + raise ValueError('The {:}-th architecture only has hyper-parameters of {:} instead of {:}.'.format(index, list(self.arch2infos_dict[arch_index].keys()), hp)) + info = self.arch2infos_dict[arch_index][hp] + strings = print_information(info, 'arch-index={:}'.format(arch_index)) + return '\n'.join(strings) + else: + print ('Find this arch-index : {:}, but this arch is not evaluated.'.format(arch_index)) + return None + + def query_meta_info_by_index(self, arch_index, hp: Text = '12'): + """Return the ArchResults for the 'arch_index'-th architecture. This function is similar to query_by_index.""" + if self.verbose: + print('Call query_meta_info_by_index with arch_index={:}, hp={:}'.format(arch_index, hp)) + if arch_index in self.arch2infos_dict: + if hp not in self.arch2infos_dict[arch_index]: + raise ValueError('The {:}-th architecture only has hyper-parameters of {:} instead of {:}.'.format(arch_index, list(self.arch2infos_dict[arch_index].keys()), hp)) + info = self.arch2infos_dict[arch_index][hp] + else: + raise ValueError('arch_index [{:}] does not in arch2infos'.format(arch_index)) + return copy.deepcopy(info) + + def query_by_index(self, arch_index: int, dataname: Union[None, Text] = None, hp: Text = '12'): + """ This 'query_by_index' function is used to query information with the training of 01 epochs, 12 epochs, 90 epochs, or 200 epochs. + ------ + If hp=01, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/01E.config) + If hp=12, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/12E.config) + If hp=90, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/90E.config) + If hp=200, we train the model by 01 epochs (see config in configs/nas-benchmark/hyper-opts/200E.config) + ------ + If dataname is None, return the ArchResults + else, return a dict with all trials on that dataset (the key is the seed) + Options are 'cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'. + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + """ + if self.verbose: + print('Call query_by_index with arch_index={:}, dataname={:}, hp={:}'.format(arch_index, dataname, hp)) + info = self.query_meta_info_by_index(arch_index, hp) + if dataname is None: return info + else: + if dataname not in info.get_dataset_names(): + raise ValueError('invalid dataset-name : {:} vs. {:}'.format(dataname, info.get_dataset_names())) + return info.query(dataname) + + def find_best(self, dataset, metric_on_set, FLOP_max=None, Param_max=None, hp: Text = '12'): + """Find the architecture with the highest accuracy based on some constraints.""" + if self.verbose: + print('Call find_best with dataset={:}, metric_on_set={:}, hp={:} | with #FLOPs < {:} and #Params < {:}'.format(dataset, metric_on_set, hp, FLOP_max, Param_max)) + dataset, metric_on_set = remap_dataset_set_names(dataset, metric_on_set, self.verbose) + best_index, highest_accuracy = -1, None + for i, arch_index in enumerate(self.evaluated_indexes): + arch_info = self.arch2infos_dict[arch_index][hp] + info = arch_info.get_compute_costs(dataset) # the information of costs + flop, param, latency = info['flops'], info['params'], info['latency'] + if FLOP_max is not None and flop > FLOP_max : continue + if Param_max is not None and param > Param_max: continue + xinfo = arch_info.get_metrics(dataset, metric_on_set) # the information of loss and accuracy + loss, accuracy = xinfo['loss'], xinfo['accuracy'] + if best_index == -1: + best_index, highest_accuracy = arch_index, accuracy + elif highest_accuracy < accuracy: + best_index, highest_accuracy = arch_index, accuracy + if self.verbose: + print(' the best architecture : [{:}] {:} with accuracy={:.3f}%'.format(best_index, self.arch(best_index), highest_accuracy)) + return best_index, highest_accuracy + + def get_net_param(self, index, dataset, seed: Optional[int], hp: Text = '12'): + """ + This function is used to obtain the trained weights of the `index`-th architecture on `dataset` with the seed of `seed` + Args [seed]: + -- None : return a dict containing the trained weights of all trials, where each key is a seed and its corresponding value is the weights. + -- a interger : return the weights of a specific trial, whose seed is this interger. + Args [hp]: + -- 01 : train the model by 01 epochs + -- 12 : train the model by 12 epochs + -- 90 : train the model by 90 epochs + -- 200 : train the model by 200 epochs + """ + if self.verbose: + print('Call the get_net_param function with index={:}, dataset={:}, seed={:}, hp={:}'.format(index, dataset, seed, hp)) + info = self.query_meta_info_by_index(index, hp) + return info.get_net_param(dataset, seed) + + def get_net_config(self, index: int, dataset: Text): + """ + This function is used to obtain the configuration for the `index`-th architecture on `dataset`. + Args [dataset] (4 possible options): + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + This function will return a dict. + ========= Some examlpes for using this function: + config = api.get_net_config(128, 'cifar10') + """ + if self.verbose: + print('Call the get_net_config function with index={:}, dataset={:}.'.format(index, dataset)) + if index in self.arch2infos_dict: + info = self.arch2infos_dict[index] + else: + raise ValueError('The arch_index={:} is not in arch2infos_dict.'.format(arch_index)) + info = next(iter(info.values())) + results = info.query(dataset, None) + results = next(iter(results.values())) + return results.get_config(None) + + def get_cost_info(self, index: int, dataset: Text, hp: Text = '12') -> Dict[Text, float]: + """To obtain the cost metric for the `index`-th architecture on a dataset.""" + if self.verbose: + print('Call the get_cost_info function with index={:}, dataset={:}, and hp={:}.'.format(index, dataset, hp)) + info = self.query_meta_info_by_index(index, hp) + return info.get_compute_costs(dataset) + + def get_latency(self, index: int, dataset: Text, hp: Text = '12') -> float: + """ + To obtain the latency of the network (by default it will return the latency with the batch size of 256). + :param index: the index of the target architecture + :param dataset: the dataset name (cifar10-valid, cifar10, cifar100, ImageNet16-120) + :return: return a float value in seconds + """ + if self.verbose: + print('Call the get_latency function with index={:}, dataset={:}, and hp={:}.'.format(index, dataset, hp)) + cost_dict = self.get_cost_info(index, dataset, hp) + return cost_dict['latency'] + + @abc.abstractmethod + def show(self, index=-1): + """This function will print the information of a specific (or all) architecture(s).""" + + def _show(self, index=-1, print_information=None) -> None: + """ + This function will print the information of a specific (or all) architecture(s). + + :param index: If the index < 0: it will loop for all architectures and print their information one by one. + else: it will print the information of the 'index'-th architecture. + :return: nothing + """ + if index < 0: # show all architectures + print(self) + for i, idx in enumerate(self.evaluated_indexes): + print('\n' + '-' * 10 + ' The ({:5d}/{:5d}) {:06d}-th architecture! '.format(i, len(self.evaluated_indexes), idx) + '-'*10) + print('arch : {:}'.format(self.meta_archs[idx])) + for key, result in self.arch2infos_dict[index].items(): + strings = print_information(result) + print('>' * 40 + ' {:03d} epochs '.format(result.get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + print('<' * 40 + '------------' + '<' * 40) + else: + if 0 <= index < len(self.meta_archs): + if index not in self.evaluated_indexes: print('The {:}-th architecture has not been evaluated or not saved.'.format(index)) + else: + arch_info = self.arch2infos_dict[index] + for key, result in self.arch2infos_dict[index].items(): + strings = print_information(result) + print('>' * 40 + ' {:03d} epochs '.format(result.get_total_epoch()) + '>' * 40) + print('\n'.join(strings)) + print('<' * 40 + '------------' + '<' * 40) + else: + print('This index ({:}) is out of range (0~{:}).'.format(index, len(self.meta_archs))) + + def statistics(self, dataset: Text, hp: Union[Text, int]) -> Dict[int, int]: + """This function will count the number of total trials.""" + if self.verbose: + print('Call the statistics function with dataset={:} and hp={:}.'.format(dataset, hp)) + valid_datasets = ['cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'] + if dataset not in valid_datasets: + raise ValueError('{:} not in {:}'.format(dataset, valid_datasets)) + nums, hp = defaultdict(lambda: 0), str(hp) + for index in range(len(self)): + archInfo = self.arch2infos_dict[index][hp] + dataset_seed = archInfo.dataset_seed + if dataset not in dataset_seed: + nums[0] += 1 + else: + nums[len(dataset_seed[dataset])] += 1 + return dict(nums) + + +class ArchResults(object): + + def __init__(self, arch_index, arch_str): + self.arch_index = int(arch_index) + self.arch_str = copy.deepcopy(arch_str) + self.all_results = dict() + self.dataset_seed = dict() + self.clear_net_done = False + + def get_compute_costs(self, dataset): + x_seeds = self.dataset_seed[dataset] + results = [self.all_results[ (dataset, seed) ] for seed in x_seeds] + + flops = [result.flop for result in results] + params = [result.params for result in results] + latencies = [result.get_latency() for result in results] + latencies = [x for x in latencies if x > 0] + mean_latency = np.mean(latencies) if len(latencies) > 0 else None + time_infos = defaultdict(list) + for result in results: + time_info = result.get_times() + for key, value in time_info.items(): time_infos[key].append( value ) + + info = {'flops' : np.mean(flops), + 'params' : np.mean(params), + 'latency': mean_latency} + for key, value in time_infos.items(): + if len(value) > 0 and value[0] is not None: + info[key] = np.mean(value) + else: info[key] = None + return info + + def get_metrics(self, dataset, setname, iepoch=None, is_random=False): + """ + This `get_metrics` function is used to obtain obtain the loss, accuracy, etc information on a specific dataset. + If not specify, each set refer to the proposed split in NAS-Bench-201 paper. + If some args return None or raise error, then it is not avaliable. + ======================================== + Args [dataset] (4 possible options): + -- cifar10-valid : training the model on the CIFAR-10 training set. + -- cifar10 : training the model on the CIFAR-10 training + validation set. + -- cifar100 : training the model on the CIFAR-100 training set. + -- ImageNet16-120 : training the model on the ImageNet16-120 training set. + Args [setname] (each dataset has different setnames): + -- When dataset = cifar10-valid, you can use 'train', 'x-valid', 'ori-test' + ------ 'train' : the metric on the training set. + ------ 'x-valid' : the metric on the validation set. + ------ 'ori-test' : the metric on the test set. + -- When dataset = cifar10, you can use 'train', 'ori-test'. + ------ 'train' : the metric on the training + validation set. + ------ 'ori-test' : the metric on the test set. + -- When dataset = cifar100 or ImageNet16-120, you can use 'train', 'ori-test', 'x-valid', 'x-test' + ------ 'train' : the metric on the training set. + ------ 'x-valid' : the metric on the validation set. + ------ 'x-test' : the metric on the test set. + ------ 'ori-test' : the metric on the validation + test set. + Args [iepoch] (None or an integer in [0, the-number-of-total-training-epochs) + ------ None : return the metric after the last training epoch. + ------ an integer i : return the metric after the i-th training epoch. + Args [is_random]: + ------ True : return the metric of a randomly selected trial. + ------ False : return the averaged metric of all avaliable trials. + ------ an integer indicating the 'seed' value : return the metric of a specific trial (whose random seed is 'is_random'). + """ + x_seeds = self.dataset_seed[dataset] + results = [self.all_results[ (dataset, seed) ] for seed in x_seeds] + infos = defaultdict(list) + for result in results: + if setname == 'train': + info = result.get_train(iepoch) + else: + info = result.get_eval(setname, iepoch) + for key, value in info.items(): infos[key].append( value ) + return_info = dict() + if isinstance(is_random, bool) and is_random: # randomly select one + index = random.randint(0, len(results)-1) + for key, value in infos.items(): return_info[key] = value[index] + elif isinstance(is_random, bool) and not is_random: # average + for key, value in infos.items(): + if len(value) > 0 and value[0] is not None: + return_info[key] = np.mean(value) + else: return_info[key] = None + elif isinstance(is_random, int): # specify the seed + if is_random not in x_seeds: raise ValueError('can not find random seed ({:}) from {:}'.format(is_random, x_seeds)) + index = x_seeds.index(is_random) + for key, value in infos.items(): return_info[key] = value[index] + else: + raise ValueError('invalid value for is_random: {:}'.format(is_random)) + return return_info + + def show(self, is_print=False): + return print_information(self, None, is_print) + + def get_dataset_names(self): + return list(self.dataset_seed.keys()) + + def get_dataset_seeds(self, dataset): + return copy.deepcopy( self.dataset_seed[dataset] ) + + def get_net_param(self, dataset: Text, seed: Union[None, int] =None): + """ + This function will return the trained network's weights on the 'dataset'. + :arg + dataset: one of 'cifar10-valid', 'cifar10', 'cifar100', and 'ImageNet16-120'. + seed: an integer indicates the seed value or None that indicates returing all trials. + """ + if seed is None: + x_seeds = self.dataset_seed[dataset] + return {seed: self.all_results[(dataset, seed)].get_net_param() for seed in x_seeds} + else: + xkey = (dataset, seed) + if xkey in self.all_results: + return self.all_results[xkey].get_net_param() + else: + raise ValueError('key={:} not in {:}'.format(xkey, list(self.all_results.keys()))) + + def reset_latency(self, dataset: Text, seed: Union[None, Text], latency: float) -> None: + """This function is used to reset the latency in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].update_latency([latency]) + else: + self.all_results[(dataset, seed)].update_latency([latency]) + + def reset_pseudo_train_times(self, dataset: Text, seed: Union[None, Text], estimated_per_epoch_time: float) -> None: + """This function is used to reset the train-times in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].reset_pseudo_train_times(estimated_per_epoch_time) + else: + self.all_results[(dataset, seed)].reset_pseudo_train_times(estimated_per_epoch_time) + + def reset_pseudo_eval_times(self, dataset: Text, seed: Union[None, Text], eval_name: Text, estimated_per_epoch_time: float) -> None: + """This function is used to reset the eval-times in all corresponding ResultsCount(s).""" + if seed is None: + for seed in self.dataset_seed[dataset]: + self.all_results[(dataset, seed)].reset_pseudo_eval_times(eval_name, estimated_per_epoch_time) + else: + self.all_results[(dataset, seed)].reset_pseudo_eval_times(eval_name, estimated_per_epoch_time) + + def get_latency(self, dataset: Text) -> float: + """Get the latency of a model on the target dataset. [Timestamp: 2020.03.09]""" + latencies = [] + for seed in self.dataset_seed[dataset]: + latency = self.all_results[(dataset, seed)].get_latency() + if not isinstance(latency, float) or latency <= 0: + raise ValueError('invalid latency of {:} with seed={:} : {:}'.format(dataset, seed, latency)) + latencies.append(latency) + return sum(latencies) / len(latencies) + + def get_total_epoch(self, dataset=None): + """Return the total number of training epochs.""" + if dataset is None: + epochss = [] + for xdata, x_seeds in self.dataset_seed.items(): + epochss += [self.all_results[(xdata, seed)].get_total_epoch() for seed in x_seeds] + elif isinstance(dataset, str): + x_seeds = self.dataset_seed[dataset] + epochss = [self.all_results[(dataset, seed)].get_total_epoch() for seed in x_seeds] + else: + raise ValueError('invalid dataset={:}'.format(dataset)) + if len(set(epochss)) > 1: raise ValueError('Each trial mush have the same number of training epochs : {:}'.format(epochss)) + return epochss[-1] + + def query(self, dataset, seed=None): + """Return the ResultsCount object (containing all information of a single trial) for 'dataset' and 'seed'""" + if seed is None: + #print(self.dataset_seed.keys()) + #print(dataset) + x_seeds = self.dataset_seed[dataset] + return {seed: self.all_results[(dataset, seed)] for seed in x_seeds} + else: + return self.all_results[(dataset, seed)] + + def arch_idx_str(self): + return '{:06d}'.format(self.arch_index) + + def update(self, dataset_name, seed, result): + if dataset_name not in self.dataset_seed: + self.dataset_seed[dataset_name] = [] + assert seed not in self.dataset_seed[dataset_name], '{:}-th arch alreadly has this seed ({:}) on {:}'.format(self.arch_index, seed, dataset_name) + self.dataset_seed[ dataset_name ].append( seed ) + self.dataset_seed[ dataset_name ] = sorted( self.dataset_seed[ dataset_name ] ) + assert (dataset_name, seed) not in self.all_results + self.all_results[ (dataset_name, seed) ] = result + self.clear_net_done = False + + def state_dict(self): + state_dict = dict() + for key, value in self.__dict__.items(): + if key == 'all_results': # contain the class of ResultsCount + xvalue = dict() + assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value)) + for _k, _v in value.items(): + assert isinstance(_v, ResultsCount), 'invalid type of value for {:}/{:} : {:}'.format(key, _k, type(_v)) + xvalue[_k] = _v.state_dict() + else: + xvalue = value + state_dict[key] = xvalue + return state_dict + + def load_state_dict(self, state_dict): + new_state_dict = dict() + for key, value in state_dict.items(): + if key == 'all_results': # to convert to the class of ResultsCount + xvalue = dict() + assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value)) + for _k, _v in value.items(): + xvalue[_k] = ResultsCount.create_from_state_dict(_v) + else: xvalue = value + new_state_dict[key] = xvalue + self.__dict__.update(new_state_dict) + + @staticmethod + def create_from_state_dict(state_dict_or_file): + x = ArchResults(-1, -1) + if isinstance(state_dict_or_file, str): # a file path + state_dict = torch.load(state_dict_or_file, map_location='cpu') + elif isinstance(state_dict_or_file, dict): + state_dict = state_dict_or_file + else: + raise ValueError('invalid type of state_dict_or_file : {:}'.format(type(state_dict_or_file))) + x.load_state_dict(state_dict) + return x + + # This function is used to clear the weights saved in each 'result' + # This can help reduce the memory footprint. + def clear_params(self): + for key, result in self.all_results.items(): + del result.net_state_dict + result.net_state_dict = None + self.clear_net_done = True + + def debug_test(self): + """This function is used for me to debug and test, which will call most methods.""" + all_dataset = ['cifar10-valid', 'cifar10', 'cifar100', 'ImageNet16-120'] + for dataset in all_dataset: + print('---->>>> {:}'.format(dataset)) + print('The latency on {:} is {:} s'.format(dataset, self.get_latency(dataset))) + for seed in self.dataset_seed[dataset]: + result = self.all_results[(dataset, seed)] + print(' ==>> result = {:}'.format(result)) + print(' ==>> cost = {:}'.format(result.get_times())) + + def __repr__(self): + return ('{name}(arch-index={index}, arch={arch}, {num} runs, clear={clear})'.format(name=self.__class__.__name__, index=self.arch_index, arch=self.arch_str, num=len(self.all_results), clear=self.clear_net_done)) + + +""" +This class (ResultsCount) is used to save the information of one trial for a single architecture. +I did not write much comment for this class, because it is the lowest-level class in NAS-Bench-201 API, which will be rarely called. +If you have any question regarding this class, please open an issue or email me. +""" +class ResultsCount(object): + + def __init__(self, name, state_dict, train_accs, train_losses, params, flop, arch_config, seed, epochs, latency): + self.name = name + self.net_state_dict = state_dict + self.train_acc1es = copy.deepcopy(train_accs) + self.train_acc5es = None + self.train_losses = copy.deepcopy(train_losses) + self.train_times = None + self.arch_config = copy.deepcopy(arch_config) + self.params = params + self.flop = flop + self.seed = seed + self.epochs = epochs + self.latency = latency + # evaluation results + self.reset_eval() + + def update_train_info(self, train_acc1es, train_acc5es, train_losses, train_times) -> None: + self.train_acc1es = train_acc1es + self.train_acc5es = train_acc5es + self.train_losses = train_losses + self.train_times = train_times + + def reset_pseudo_train_times(self, estimated_per_epoch_time: float) -> None: + """Assign the training times.""" + train_times = OrderedDict() + for i in range(self.epochs): + train_times[i] = estimated_per_epoch_time + self.train_times = train_times + + def reset_pseudo_eval_times(self, eval_name: Text, estimated_per_epoch_time: float) -> None: + """Assign the evaluation times.""" + if eval_name not in self.eval_names: raise ValueError('invalid eval name : {:}'.format(eval_name)) + for i in range(self.epochs): + self.eval_times['{:}@{:}'.format(eval_name,i)] = estimated_per_epoch_time + + def reset_eval(self): + self.eval_names = [] + self.eval_acc1es = {} + self.eval_times = {} + self.eval_losses = {} + + def update_latency(self, latency): + self.latency = copy.deepcopy( latency ) + + def get_latency(self) -> float: + """Return the latency value in seconds. -1 represents not avaliable ; otherwise it should be a float value""" + if self.latency is None: return -1.0 + else: return sum(self.latency) / len(self.latency) + + def update_eval(self, accs, losses, times): # new version + data_names = set([x.split('@')[0] for x in accs.keys()]) + for data_name in data_names: + assert data_name not in self.eval_names, '{:} has already been added into eval-names'.format(data_name) + self.eval_names.append( data_name ) + for iepoch in range(self.epochs): + xkey = '{:}@{:}'.format(data_name, iepoch) + self.eval_acc1es[ xkey ] = accs[ xkey ] + self.eval_losses[ xkey ] = losses[ xkey ] + self.eval_times [ xkey ] = times[ xkey ] + + def update_OLD_eval(self, name, accs, losses): # old version + assert name not in self.eval_names, '{:} has already added'.format(name) + self.eval_names.append( name ) + for iepoch in range(self.epochs): + if iepoch in accs: + self.eval_acc1es['{:}@{:}'.format(name,iepoch)] = accs[iepoch] + self.eval_losses['{:}@{:}'.format(name,iepoch)] = losses[iepoch] + + def __repr__(self): + num_eval = len(self.eval_names) + set_name = '[' + ', '.join(self.eval_names) + ']' + return ('{name}({xname}, arch={arch}, FLOP={flop:.2f}M, Param={param:.3f}MB, seed={seed}, {num_eval} eval-sets: {set_name})'.format(name=self.__class__.__name__, xname=self.name, arch=self.arch_config['arch_str'], flop=self.flop, param=self.params, seed=self.seed, num_eval=num_eval, set_name=set_name)) + + def get_total_epoch(self): + return copy.deepcopy(self.epochs) + + def get_times(self): + """Obtain the information regarding both training and evaluation time.""" + if self.train_times is not None and isinstance(self.train_times, dict): + train_times = list( self.train_times.values() ) + time_info = {'T-train@epoch': np.mean(train_times), 'T-train@total': np.sum(train_times)} + else: + time_info = {'T-train@epoch': None, 'T-train@total': None } + for name in self.eval_names: + try: + xtimes = [self.eval_times['{:}@{:}'.format(name,i)] for i in range(self.epochs)] + time_info['T-{:}@epoch'.format(name)] = np.mean(xtimes) + time_info['T-{:}@total'.format(name)] = np.sum(xtimes) + except: + time_info['T-{:}@epoch'.format(name)] = None + time_info['T-{:}@total'.format(name)] = None + return time_info + + def get_eval_set(self): + return self.eval_names + + # get the training information + def get_train(self, iepoch=None): + if iepoch is None: iepoch = self.epochs-1 + assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs) + if self.train_times is not None: + xtime = self.train_times[iepoch] + atime = sum([self.train_times[i] for i in range(iepoch+1)]) + else: xtime, atime = None, None + return {'iepoch' : iepoch, + 'loss' : self.train_losses[iepoch], + 'accuracy': self.train_acc1es[iepoch], + 'cur_time': xtime, + 'all_time': atime} + + def get_eval(self, name, iepoch=None): + """Get the evaluation information ; there could be multiple evaluation sets (identified by the 'name' argument).""" + if iepoch is None: iepoch = self.epochs-1 + assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs) + def _internal_query(xname): + if isinstance(self.eval_times,dict) and len(self.eval_times) > 0: + xtime = self.eval_times['{:}@{:}'.format(xname, iepoch)] + atime = sum([self.eval_times['{:}@{:}'.format(xname, i)] for i in range(iepoch+1)]) + else: + xtime, atime = None, None + return {'iepoch' : iepoch, + 'loss' : self.eval_losses['{:}@{:}'.format(xname, iepoch)], + 'accuracy': self.eval_acc1es['{:}@{:}'.format(xname, iepoch)], + 'cur_time': xtime, + 'all_time': atime} + if name == 'valid': + return _internal_query('x-valid') + else: + return _internal_query(name) + + def get_net_param(self, clone=False): + if clone: return copy.deepcopy(self.net_state_dict) + else: return self.net_state_dict + + def get_config(self, str2structure): + """This function is used to obtain the config dict for this architecture.""" + if str2structure is None: + # In this case, this is to handle the size search space. + if 'name' in self.arch_config and self.arch_config['name'] == 'infer.shape.tiny': + return {'name': 'infer.shape.tiny', 'channels': self.arch_config['channels'], + 'genotype': self.arch_config['genotype'], 'num_classes': self.arch_config['class_num']} + # In this case, this is NAS-Bench-201 + else: + return {'name': 'infer.tiny', 'C': self.arch_config['channel'], + 'N' : self.arch_config['num_cells'], + 'arch_str': self.arch_config['arch_str'], 'num_classes': self.arch_config['class_num']} + else: + # In this case, this is to handle the size search space. + if 'name' in self.arch_config and self.arch_config['name'] == 'infer.shape.tiny': + return {'name': 'infer.shape.tiny', 'channels': self.arch_config['channels'], + 'genotype': str2structure(self.arch_config['genotype']), 'num_classes': self.arch_config['class_num']} + # In this case, this is NAS-Bench-201 + else: + return {'name': 'infer.tiny', 'C': self.arch_config['channel'], + 'N' : self.arch_config['num_cells'], + 'genotype': str2structure(self.arch_config['arch_str']), 'num_classes': self.arch_config['class_num']} + + def state_dict(self): + _state_dict = {key: value for key, value in self.__dict__.items()} + return _state_dict + + def load_state_dict(self, state_dict): + self.__dict__.update(state_dict) + + @staticmethod + def create_from_state_dict(state_dict): + x = ResultsCount(None, None, None, None, None, None, None, None, None, None) + x.load_state_dict(state_dict) + return x diff --git a/nasspace.py b/nasspace.py new file mode 100644 index 0000000..b87eb58 --- /dev/null +++ b/nasspace.py @@ -0,0 +1,360 @@ +from models import get_cell_based_tiny_net, get_search_spaces +from nas_201_api import NASBench201API as API +from nasbench import api as nasbench101api +from nas_101_api.model import Network +from nas_101_api.model_spec import ModelSpec +import itertools +import random +import numpy as np +from models.cell_searchs.genotypes import Structure +from copy import deepcopy +from pycls.models.nas.nas import NetworkImageNet, NetworkCIFAR +from pycls.models.anynet import AnyNet +from pycls.models.nas.genotypes import GENOTYPES, Genotype +import json +import torch + + +class Nasbench201: + def __init__(self, dataset, apiloc): + self.dataset = dataset + self.api = API(apiloc, verbose=False) + self.epochs = '12' + def get_network(self, uid): + #config = self.api.get_net_config(uid, self.dataset) + config = self.api.get_net_config(uid, 'cifar10-valid') + config['num_classes'] = 1 + network = get_cell_based_tiny_net(config) + return network + def __iter__(self): + for uid in range(len(self)): + network = self.get_network(uid) + yield uid, network + def __getitem__(self, index): + return index + def __len__(self): + return 15625 + def num_activations(self): + network = self.get_network(0) + return network.classifier.in_features + #def get_12epoch_accuracy(self, uid, acc_type, trainval, traincifar10=False): + # archinfo = self.api.query_meta_info_by_index(uid) + # if (self.dataset == 'cifar10' or traincifar10) and trainval: + # #return archinfo.get_metrics('cifar10-valid', acc_type, iepoch=12)['accuracy'] + # return archinfo.get_metrics('cifar10-valid', 'x-valid', iepoch=12)['accuracy'] + # elif traincifar10: + # return archinfo.get_metrics('cifar10', acc_type, iepoch=12)['accuracy'] + # else: + # return archinfo.get_metrics(self.dataset, 'ori-test', iepoch=12)['accuracy'] + def get_12epoch_accuracy(self, uid, acc_type, trainval, traincifar10=False): + #archinfo = self.api.query_meta_info_by_index(uid) + #if (self.dataset == 'cifar10' and trainval) or traincifar10: + info = self.api.get_more_info(uid, 'cifar10-valid', iepoch=None, hp=self.epochs, is_random=True) + #else: + # info = self.api.get_more_info(uid, self.dataset, iepoch=None, hp=self.epochs, is_random=True) + return info['valid-accuracy'] + def get_final_accuracy(self, uid, acc_type, trainval): + #archinfo = self.api.query_meta_info_by_index(uid) + if self.dataset == 'cifar10' and trainval: + info = self.api.query_meta_info_by_index(uid, hp='200').get_metrics('cifar10-valid', 'x-valid') + #info = self.api.query_by_index(uid, 'cifar10-valid', hp='200') + #info = self.api.get_more_info(uid, 'cifar10-valid', iepoch=None, hp='200', is_random=True) + else: + info = self.api.query_meta_info_by_index(uid, hp='200').get_metrics(self.dataset, acc_type) + #info = self.api.query_by_index(uid, self.dataset, hp='200') + #info = self.api.get_more_info(uid, self.dataset, iepoch=None, hp='200', is_random=True) + return info['accuracy'] + #return info['valid-accuracy'] + #if self.dataset == 'cifar10' and trainval: + # return archinfo.get_metrics('cifar10-valid', acc_type, iepoch=11)['accuracy'] + #else: + # #return archinfo.get_metrics(self.dataset, 'ori-test', iepoch=12)['accuracy'] + # return archinfo.get_metrics(self.dataset, 'x-test', iepoch=11)['accuracy'] + ##dataset = self.dataset + ##if self.dataset == 'cifar10' and trainval: + ## dataset = 'cifar10-valid' + ##archinfo = self.api.get_more_info(uid, dataset, iepoch=None, use_12epochs_result=True, is_random=True) + ##return archinfo['valid-accuracy'] + + def get_accuracy(self, uid, acc_type, trainval=True): + archinfo = self.api.query_meta_info_by_index(uid) + if self.dataset == 'cifar10' and trainval: + return archinfo.get_metrics('cifar10-valid', acc_type)['accuracy'] + else: + return archinfo.get_metrics(self.dataset, acc_type)['accuracy'] + + def get_accuracy_for_all_datasets(self, uid): + archinfo = self.api.query_meta_info_by_index(uid,hp='200') + + c10 = archinfo.get_metrics('cifar10', 'ori-test')['accuracy'] + c10_val = archinfo.get_metrics('cifar10-valid', 'x-valid')['accuracy'] + + c100 = archinfo.get_metrics('cifar100', 'x-test')['accuracy'] + c100_val = archinfo.get_metrics('cifar100', 'x-valid')['accuracy'] + + imagenet = archinfo.get_metrics('ImageNet16-120', 'x-test')['accuracy'] + imagenet_val = archinfo.get_metrics('ImageNet16-120', 'x-valid')['accuracy'] + + return c10, c10_val, c100, c100_val, imagenet, imagenet_val + + #def train_and_eval(self, arch, dataname, acc_type, trainval=True): + # unique_hash = self.__getitem__(arch) + # time = self.get_training_time(unique_hash) + # acc12 = self.get_12epoch_accuracy(unique_hash, acc_type, trainval) + # acc = self.get_final_accuracy(unique_hash, acc_type, trainval) + # return acc12, acc, time + def train_and_eval(self, arch, dataname, acc_type, trainval=True, traincifar10=False): + unique_hash = self.__getitem__(arch) + time = self.get_training_time(unique_hash) + acc12 = self.get_12epoch_accuracy(unique_hash, acc_type, trainval, traincifar10) + acc = self.get_final_accuracy(unique_hash, acc_type, trainval) + return acc12, acc, time + def random_arch(self): + return random.randint(0, len(self)-1) + def get_training_time(self, unique_hash): + #info = self.api.get_more_info(unique_hash, 'cifar10-valid' if self.dataset == 'cifar10' else self.dataset, iepoch=None, use_12epochs_result=True, is_random=True) + + + #info = self.api.get_more_info(unique_hash, 'cifar10-valid', iepoch=None, use_12epochs_result=True, is_random=True) + info = self.api.get_more_info(unique_hash, 'cifar10-valid', iepoch=None, hp='12', is_random=True) + return info['train-all-time'] + info['valid-per-time'] + #if self.dataset == 'cifar10' and trainval: + # info = self.api.get_more_info(unique_hash, 'cifar10-valid', iepoch=None, hp=self.epochs, is_random=True) + #else: + # info = self.api.get_more_info(unique_hash, self.dataset, iepoch=None, hp=self.epochs, is_random=True) + + ##info = self.api.get_more_info(unique_hash, 'cifar10-valid', iepoch=None, use_12epochs_result=True, is_random=True) + #return info['train-all-time'] + info['valid-per-time'] + def mutate_arch(self, arch): + op_names = get_search_spaces('cell', 'nas-bench-201') + #config = self.api.get_net_config(arch, self.dataset) + config = self.api.get_net_config(arch, 'cifar10-valid') + parent_arch = Structure(self.api.str2lists(config['arch_str'])) + child_arch = deepcopy( parent_arch ) + node_id = random.randint(0, len(child_arch.nodes)-1) + node_info = list( child_arch.nodes[node_id] ) + snode_id = random.randint(0, len(node_info)-1) + xop = random.choice( op_names ) + while xop == node_info[snode_id][0]: + xop = random.choice( op_names ) + node_info[snode_id] = (xop, node_info[snode_id][1]) + child_arch.nodes[node_id] = tuple( node_info ) + arch_index = self.api.query_index_by_arch( child_arch ) + return arch_index + +class Nasbench101: + def __init__(self, dataset, apiloc, args): + self.dataset = dataset + self.api = nasbench101api.NASBench(apiloc) + self.args = args + def get_accuracy(self, unique_hash, acc_type, trainval=True): + spec = self.get_spec(unique_hash) + _, stats = self.api.get_metrics_from_spec(spec) + maxacc = 0. + for ep in stats: + for statmap in stats[ep]: + newacc = statmap['final_test_accuracy'] + if newacc > maxacc: + maxacc = newacc + return maxacc + def get_final_accuracy(self, uid, acc_type, trainval): + return self.get_accuracy(uid, acc_type, trainval) + def get_training_time(self, unique_hash): + spec = self.get_spec(unique_hash) + _, stats = self.api.get_metrics_from_spec(spec) + maxacc = -1. + maxtime = 0. + for ep in stats: + for statmap in stats[ep]: + newacc = statmap['final_test_accuracy'] + if newacc > maxacc: + maxacc = newacc + maxtime = statmap['final_training_time'] + return maxtime + def get_network(self, unique_hash): + spec = self.get_spec(unique_hash) + network = Network(spec, self.args) + return network + def get_spec(self, unique_hash): + matrix = self.api.fixed_statistics[unique_hash]['module_adjacency'] + operations = self.api.fixed_statistics[unique_hash]['module_operations'] + spec = ModelSpec(matrix, operations) + return spec + def __iter__(self): + for unique_hash in self.api.hash_iterator(): + network = self.get_network(unique_hash) + yield unique_hash, network + def __getitem__(self, index): + return next(itertools.islice(self.api.hash_iterator(), index, None)) + def __len__(self): + return len(self.api.hash_iterator()) + def num_activations(self): + for unique_hash in self.api.hash_iterator(): + network = self.get_network(unique_hash) + return network.classifier.in_features + def train_and_eval(self, arch, dataname, acc_type, trainval=True, traincifar10=False): + unique_hash = self.__getitem__(arch) + time =12.* self.get_training_time(unique_hash)/108. + acc = self.get_accuracy(unique_hash, acc_type, trainval) + return acc, acc, time + def random_arch(self): + return random.randint(0, len(self)-1) + def mutate_arch(self, arch): + unique_hash = self.__getitem__(arch) + matrix = self.api.fixed_statistics[unique_hash]['module_adjacency'] + operations = self.api.fixed_statistics[unique_hash]['module_operations'] + coords = [ (i, j) for i in range(matrix.shape[0]) for j in range(i+1, matrix.shape[1])] + random.shuffle(coords) + # loop through changes until we find change thats allowed + for i, j in coords: + # try the ops in a particular order + for k in [m for m in np.unique(matrix) if m != matrix[i, j]]: + newmatrix = matrix.copy() + newmatrix[i, j] = k + spec = ModelSpec(newmatrix, operations) + try: + newhash = self.api._hash_spec(spec) + if newhash in self.api.fixed_statistics: + return [n for n, m in enumerate(self.api.fixed_statistics.keys()) if m == newhash][0] + except: + pass + + + + +class ReturnFeatureLayer(torch.nn.Module): + def __init__(self, mod): + super(ReturnFeatureLayer, self).__init__() + self.mod = mod + def forward(self, x): + return self.mod(x), x + + +def return_feature_layer(network, prefix=''): + #for attr_str in dir(network): + # target_attr = getattr(network, attr_str) + # if isinstance(target_attr, torch.nn.Linear): + # setattr(network, attr_str, ReturnFeatureLayer(target_attr)) + for n, ch in list(network.named_children()): + if isinstance(ch, torch.nn.Linear): + setattr(network, n, ReturnFeatureLayer(ch)) + else: + return_feature_layer(ch, prefix + '\t') + + +class NDS: + def __init__(self, searchspace): + self.searchspace = searchspace + data = json.load(open(f'nds_data/{searchspace}.json', 'r')) + try: + data = data['top'] + data['mid'] + except Exception as e: + pass + self.data = data + def __iter__(self): + for unique_hash in range(len(self)): + network = self.get_network(unique_hash) + yield unique_hash, network + def get_network_config(self, uid): + return self.data[uid]['net'] + def get_network_optim_config(self, uid): + return self.data[uid]['optim'] + def get_network(self, uid): + netinfo = self.data[uid] + config = netinfo['net'] + #print(config) + if 'genotype' in config: + #print('geno') + gen = config['genotype'] + genotype = Genotype(normal=gen['normal'], normal_concat=gen['normal_concat'], reduce=gen['reduce'], reduce_concat=gen['reduce_concat']) + if '_in' in self.searchspace: + network = NetworkImageNet(config['width'], 1, config['depth'], config['aux'], genotype) + else: + network = NetworkCIFAR(config['width'], 1, config['depth'], config['aux'], genotype) + network.drop_path_prob = 0. + #print(config) + #print('genotype') + L = config['depth'] + else: + if 'bot_muls' in config and 'bms' not in config: + config['bms'] = config['bot_muls'] + del config['bot_muls'] + if 'num_gs' in config and 'gws' not in config: + config['gws'] = config['num_gs'] + del config['num_gs'] + config['nc'] = 1 + config['se_r'] = None + config['stem_w'] = 12 + L = sum(config['ds']) + if 'ResN' in self.searchspace: + config['stem_type'] = 'res_stem_in' + else: + config['stem_type'] = 'simple_stem_in' + #"res_stem_cifar": ResStemCifar, + #"res_stem_in": ResStemIN, + #"simple_stem_in": SimpleStemIN, + if config['block_type'] == 'double_plain_block': + config['block_type'] = 'vanilla_block' + network = AnyNet(**config) + return_feature_layer(network) + return network + def __getitem__(self, index): + return index + def __len__(self): + return len(self.data) + def random_arch(self): + return random.randint(0, len(self.data)-1) + def get_final_accuracy(self, uid, acc_type, trainval): + return 100.-self.data[uid]['test_ep_top1'][-1] + + +def get_search_space(args): + if args.nasspace == 'nasbench201': + return Nasbench201(args.dataset, args.api_loc) + elif args.nasspace == 'nasbench101': + return Nasbench101(args.dataset, args.api_loc, args) + elif args.nasspace == 'nds_resnet': + return NDS('ResNet') + elif args.nasspace == 'nds_amoeba': + return NDS('Amoeba') + elif args.nasspace == 'nds_amoeba_in': + return NDS('Amoeba_in') + elif args.nasspace == 'nds_darts_in': + return NDS('DARTS_in') + elif args.nasspace == 'nds_darts': + return NDS('DARTS') + elif args.nasspace == 'nds_darts_fix-w-d': + return NDS('DARTS_fix-w-d') + elif args.nasspace == 'nds_darts_lr-wd': + return NDS('DARTS_lr-wd') + elif args.nasspace == 'nds_enas': + return NDS('ENAS') + elif args.nasspace == 'nds_enas_in': + return NDS('ENAS_in') + elif args.nasspace == 'nds_enas_fix-w-d': + return NDS('ENAS_fix-w-d') + elif args.nasspace == 'nds_pnas': + return NDS('PNAS') + elif args.nasspace == 'nds_pnas_fix-w-d': + return NDS('PNAS_fix-w-d') + elif args.nasspace == 'nds_pnas_in': + return NDS('PNAS_in') + elif args.nasspace == 'nds_nasnet': + return NDS('NASNet') + elif args.nasspace == 'nds_nasnet_in': + return NDS('NASNet_in') + elif args.nasspace == 'nds_resnext-a': + return NDS('ResNeXt-A') + elif args.nasspace == 'nds_resnext-a_in': + return NDS('ResNeXt-A_in') + elif args.nasspace == 'nds_resnext-b': + return NDS('ResNeXt-B') + elif args.nasspace == 'nds_resnext-b_in': + return NDS('ResNeXt-B_in') + elif args.nasspace == 'nds_vanilla': + return NDS('Vanilla') + elif args.nasspace == 'nds_vanilla_lr-wd': + return NDS('Vanilla_lr-wd') + elif args.nasspace == 'nds_vanilla_lr-wd_in': + return NDS('Vanilla_lr-wd_in') + diff --git a/plot_histograms.py b/plot_histograms.py deleted file mode 100644 index 8af5b55..0000000 --- a/plot_histograms.py +++ /dev/null @@ -1,144 +0,0 @@ -import os -import argparse -import random -import numpy as np - -import matplotlib.pyplot as plt -from datasets import get_datasets -from config_utils import load_config - -from nas_201_api import NASBench201API as API -from models import get_cell_based_tiny_net -import torch -import torch.nn as nn - - -def get_batch_jacobian(net, data_loader, device): - data_iterator = iter(data_loader) - x, target = next(data_iterator) - x = x.to(device) - net.zero_grad() - x.requires_grad_(True) - _, y = net(x) - y.backward(torch.ones_like(y)) - jacob = x.grad.detach() - return jacob, target.detach() - -def plot_hist(jacob, ax, colour): - xx = jacob.reshape(jacob.size(0), -1).cpu().numpy() - corrs = np.corrcoef(xx) - ax.hist(corrs.flatten(), bins=100, color=colour) - -def decide_plot(acc, plt_cts, num_rows, boundaries=[60., 70., 80., 90.]): - if acc < boundaries[0]: - plt_col = 0 - accrange = f'< {boundaries[0]}%' - elif acc < boundaries[1]: - plt_col = 1 - accrange = f'[{boundaries[0]}% , {boundaries[1]}%)' - elif acc < boundaries[2]: - plt_col = 2 - accrange = f'[{boundaries[1]}% , {boundaries[2]}%)' - elif acc < boundaries[3]: - accrange = f'[{boundaries[2]}% , {boundaries[3]}%)' - plt_col = 3 - else: - accrange = f'>= {boundaries[3]}%' - plt_col = 4 - - can_plot = False - plt_row = 0 - if plt_cts[plt_col] < num_rows: - can_plot = True - plt_row = plt_cts[plt_col] - plt_cts[plt_col] += 1 - - return can_plot, plt_row, plt_col, accrange - - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Plot histograms of correlation matrix') - parser.add_argument('--data_loc', default='../datasets/cifar/', type=str, help='dataset folder') - parser.add_argument('--api_loc', default='NAS-Bench-201-v1_1-096897.pth', - type=str, help='path to API') - parser.add_argument('--arch_start', default=0, type=int) - parser.add_argument('--arch_end', default=15625, type=int) - parser.add_argument('--seed', default=42, type=int) - parser.add_argument('--GPU', default='0', type=str) - parser.add_argument('--batch_size', default=256, type=int) - - args = parser.parse_args() - os.environ['CUDA_VISIBLE_DEVICES'] = args.GPU - - # Reproducibility - torch.backends.cudnn.deterministic = True - torch.backends.cudnn.benchmark = False - random.seed(args.seed) - np.random.seed(args.seed) - torch.manual_seed(args.seed) - - device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") - - ARCH_START = args.arch_start - ARCH_END = args.arch_end - - criterion = nn.CrossEntropyLoss() - train_data, valid_data, xshape, class_num = get_datasets('cifar10', args.data_loc, 0) - - cifar_split = load_config('config_utils/cifar-split.txt', None, None) - train_split, valid_split = cifar_split.train, cifar_split.valid - train_loader = torch.utils.data.DataLoader(train_data, batch_size=args.batch_size, - num_workers=0, pin_memory=True, sampler= torch.utils.data.sampler.SubsetRandomSampler(train_split)) - - scores = [] - accs = [] - - plot_shape = (25, 5) - num_plots = plot_shape[0]*plot_shape[1] - fig, axes = plt.subplots(*plot_shape, sharex=True, figsize=(9, 9) ) - plt_cts = [0 for i in range(plot_shape[1])] - - api = API(args.api_loc) - - archs = list(range(ARCH_START, ARCH_END)) - colours = ['#811F41', '#A92941', '#D15141', '#EF7941', '#F99C4B'] - - strs = [] - random.shuffle(archs) - for arch in archs: - try: - config = api.get_net_config(arch, 'cifar10') - archinfo = api.query_meta_info_by_index(arch) - acc = archinfo.get_metrics('cifar10-valid', 'x-valid')['accuracy'] - - network = get_cell_based_tiny_net(config) - network = network.to(device) - jacobs, labels = get_batch_jacobian(network, train_loader, device) - - boundaries = [60., 70., 80., 90.] - can_plt, row, col, accrange = decide_plot(acc, plt_cts, plot_shape[0], boundaries) - if not can_plt: - continue - axes[row, col].axis('off') - - plot_hist(jacobs, axes[row, col], colours[col]) - if row == 0: - axes[row, col].set_title(f'{accrange}') - - if row + 1 == plot_shape[0]: - axes[row, col].axis('on') - plt.setp(axes[row, col].get_xticklabels(), fontsize=12) - axes[row, col].spines["top"].set_visible(False) - axes[row, col].spines["right"].set_visible(False) - axes[row, col].spines["left"].set_visible(False) - axes[row, col].set_yticks([]) - - if sum(plt_cts) == num_plots: - plt.tight_layout() - plt.savefig(f'results/histograms_cifar10val_batch{args.batch_size}.png') - plt.show() - break - except Exception as e: - plt_cts[col] -= 1 - continue diff --git a/plot_scores.py b/plot_scores.py new file mode 100644 index 0000000..7aeab45 --- /dev/null +++ b/plot_scores.py @@ -0,0 +1,285 @@ +import argparse +import random +import numpy as np +import matplotlib.pyplot as plt +import matplotlib as mp +import matplotlib +matplotlib.use('Agg') +from decimal import Decimal +from scipy.special import logit, expit +from scipy import stats +import seaborn as sns + +''' +font = { + 'size' : 18} + +matplotlib.rc('font', **font) +''' +SMALL_SIZE = 10 +MEDIUM_SIZE = 12 +BIGGER_SIZE = 14 + +plt.rc('font', size=MEDIUM_SIZE) # controls default text sizes +plt.rc('axes', titlesize=BIGGER_SIZE) # fontsize of the axes title +plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels +plt.rc('xtick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc('ytick', labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc('legend', fontsize=MEDIUM_SIZE) # legend fontsize +plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title + +parser = argparse.ArgumentParser(description='NAS Without Training') +parser.add_argument('--data_loc', default='../cifardata/', type=str, help='dataset folder') +parser.add_argument('--api_loc', default='../NAS-Bench-201-v1_0-e61699.pth', + type=str, help='path to API') +parser.add_argument('--save_loc', default='results', type=str, help='folder to save results') +parser.add_argument('--save_string', default='naswot', type=str, help='prefix of results file') +parser.add_argument('--score', default='hook_logdet', type=str, help='the score to evaluate') +parser.add_argument('--nasspace', default='nasbench201', type=str, help='the nas search space to use') +parser.add_argument('--batch_size', default=128, type=int) +parser.add_argument('--repeat', default=1, type=int, help='how often to repeat a single image with a batch') +parser.add_argument('--augtype', default='none', type=str, help='which perturbations to use') +parser.add_argument('--sigma', default=0.05, type=float, help='noise level if augtype is "gaussnoise"') +parser.add_argument('--init', default='', type=str) +parser.add_argument('--GPU', default='0', type=str) +parser.add_argument('--seed', default=1, type=int) +parser.add_argument('--trainval', action='store_true') +parser.add_argument('--dropout', action='store_true') +parser.add_argument('--dataset', default='cifar10', type=str) +parser.add_argument('--maxofn', default=1, type=int, help='score is the max of this many evaluations of the network') +parser.add_argument('--n_samples', default=100, type=int) +parser.add_argument('--n_runs', default=500, type=int) +parser.add_argument('--stem_out_channels', default=16, type=int, help='output channels of stem convolution (nasbench101)') +parser.add_argument('--num_stacks', default=3, type=int, help='#stacks of modules (nasbench101)') +parser.add_argument('--num_modules_per_stack', default=3, type=int, help='#modules per stack (nasbench101)') +parser.add_argument('--num_labels', default=1, type=int, help='#classes (nasbench101)') + +args = parser.parse_args() + +print(f'{args.batch_size}') +random.seed(args.seed) +np.random.seed(args.seed) + +filename = f'{args.save_loc}/{args.save_string}_{args.score}_{args.nasspace}_{args.dataset}{"_" + args.init + "_" if args.init != "" else args.init}_{"_dropout" if args.dropout else ""}_{args.augtype}_{args.sigma}_{args.repeat}_{args.trainval}_{args.batch_size}_{args.maxofn}_{args.seed}.npy' +accfilename = f'{args.save_loc}/{args.save_string}_accs_{args.nasspace}_{args.dataset}_{args.trainval}.npy' + +from matplotlib.colors import hsv_to_rgb +print(filename) +scores = np.load(filename) +accs = np.load(accfilename) + +def make_colours_by_hue(h, v=1.): + return [hsv_to_rgb((h1 if h1 < 1. else h1-1., s, v)) for h1, s,v in zip(np.linspace(h, h+0.05, 5), np.linspace(1., .6, 5), np.linspace(0.1, 1., 5))] +print(f'NETWORK accuracy with highest score {accs[np.argmax(scores)]}') + +make_colours = lambda cols: [mp.colors.to_rgba(c) for c in cols] +oranges = make_colours(['#811F41', '#A92941', '#D15141', '#EF7941', '#F99C4B']) +blues = make_colours(['#190C30', '#241147', '#34208C', '#4882FA', '#81BAFC']) +print(blues) +print(make_colours_by_hue(0.9)) +if args.nasspace == 'nasbench101': + #colours = blues + colours = make_colours_by_hue(0.9) +elif 'darts' in args.nasspace: + #colours = sns.color_palette("BuGn_r", n_colors=5) + colours = make_colours_by_hue(0.0) +elif 'pnas' in args.nasspace: + #colours = sns.color_palette("PuRd", n_colors=5) + colours = make_colours_by_hue(0.1) +elif args.nasspace == 'nasbench201': + #colours = oranges + colours = make_colours_by_hue(0.3) +elif 'enas' in args.nasspace: + #colours = oranges + colours = make_colours_by_hue(0.4) +elif 'resnet' in args.nasspace: + #colours = sns.color_palette("viridis_r", n_colors=5) + colours = make_colours_by_hue(0.5) +elif 'amoeba' in args.nasspace: + #colours = sns.color_palette("viridis_r", n_colors=5) + colours = make_colours_by_hue(0.6) +elif 'nasnet' in args.nasspace: + #colours = sns.color_palette("viridis_r", n_colors=5) + colours = make_colours_by_hue(0.7) +elif 'resnext-b' in args.nasspace: + #colours = sns.color_palette("viridis_r", n_colors=5) + colours = make_colours_by_hue(0.8) +else: + from zlib import crc32 + + def bytes_to_float(b): + return float(crc32(b) & 0xffffffff) / 2**32 + def str_to_float(s, encoding="utf-8"): + return bytes_to_float(s.encode(encoding)) + #colours = sns.color_palette("Purples_r", n_colors=5) + colours = make_colours_by_hue(str_to_float(args.nasspace)) + +def make_colordict(colours, points): + cdict = {'red': [[pt, colour[0], colour[0]] for pt, colour in zip(points, colours)], + 'green':[[pt, colour[1], colour[1]] for pt, colour in zip(points, colours)], + 'blue':[[pt, colour[2], colour[2]] for pt, colour in zip(points, colours)]} + return cdict + +def make_colormap(dataset, space, colours): + if dataset == 'cifar10' and 'resn' in space: + points = [0., 0.85, 0.9, 0.95, 1.0, 1.0] + colours = [colours[0]] + colours + elif dataset == 'cifar10' and 'nds_darts' in space: + points = [0., 0.8, 0.85, 0.9, 0.95, 1.0] + colours = [colours[0]] + colours + elif dataset == 'cifar10' and 'pnas' in space: + points = [0., 0.875, 0.9, 0.925, 0.95, 1.0] + colours = [colours[0]] + colours + elif dataset == 'cifar10': + points = [0., 0.6, 0.7, 0.8, 0.9, 1.0] + colours = [colours[0]] + colours + #cdict = {'red': [[0., colours[0][0], colours[0][0]]] + [[0.1*i + 0.6, colours[i][0], colours[i][0]] for i in range(len(colours))], + # 'green':[[0., colours[0][1], colours[0][1]]] + [[0.1*i + 0.6, colours[i][1], colours[i][1]] for i in range(len(colours))], + # 'blue':[[0., colours[0][2], colours[0][2]]] + [[0.1*i + 0.6, colours[i][2], colours[i][2]] for i in range(len(colours))]} + elif dataset == 'cifar100': + points = [0., 0.3, 0.4, 0.5, 0.6, 0.7, 1.0] + colours = [colours[0]] + colours + [colours[-1]] + + #cdict = {'red': [[0., colours[0][0], colours[0][0]]] + [[0.1*i + 0.3, colours[i][0], colours[i][0]] for i in range(len(colours))] + [[1., colours[-1][0], colours[-1][0]]] , + # 'green':[[0., colours[0][1], colours[0][1]]] + [[0.1*i + 0.3, colours[i][1], colours[i][1]] for i in range(len(colours))] + [[1., colours[-1][1], colours[-1][1]]] , + # 'blue':[[0., colours[0][2], colours[0][2]]] + [[0.1*i + 0.3, colours[i][2], colours[i][2]] for i in range(len(colours))] + [[1., colours[-1][2], colours[-1][2]]] } + else: + points = [0., 0.1, 0.2, 0.3, 0.4, 1.0] + colours = colours + [colours[-1]] + + #cdict = {'red': [[0.1*i, colours[i][0], colours[i][0]] for i in range(len(colours))] + [[1., colours[-1][0], colours[-1][0]]] , + # 'green': [[0.1*i, colours[i][1], colours[i][1]] for i in range(len(colours))] + [[1., colours[-1][1], colours[-1][1]]] , + # 'blue': [[0.1*i, colours[i][2], colours[i][2]] for i in range(len(colours))] + [[1., colours[-1][2], colours[-1][2]]] } + + cdict = make_colordict(colours, points) + return cdict +cdict = make_colormap(args.dataset, args.nasspace, colours) +newcmp = mp.colors.LinearSegmentedColormap('testCmap', segmentdata=cdict, N=256) + +if args.nasspace == 'nasbench101': + accs = accs[:10000] + scores = scores[:10000] + inds = accs > 0.5 + accs = accs[inds] + scores = scores[inds] + print(accs.shape) +elif args.nasspace == 'nds_amoeba' or args.nasspace == 'nds_darts_fix-w-d': + print(accs.shape) + inds = accs > 15. + accs = accs[inds] + scores = scores[inds] + print(accs.shape) +elif args.nasspace == 'nds_darts': + inds = accs > 15. + from nasspace import get_search_space + searchspace = get_search_space(args) + accs = accs[inds] + scores = scores[inds] + print(accs.shape) +else: + print(accs.shape) + inds = accs > 15. + accs = accs[inds] + scores = scores[inds] + print(accs.shape) + +inds = scores == 0. +accs = accs[~inds] +scores = scores[~inds] + + + +if accs.size > 1000: + inds = np.random.choice(accs.size, 1000, replace=False) + accs = accs[inds] + scores = scores[inds] + +inds = np.isnan(scores) +accs = accs[~inds] +scores = scores[~inds] + +tau, p = stats.kendalltau(accs, scores) + +if args.nasspace == 'nasbench101': + fig, ax = plt.subplots(1, 1, figsize=(5,5)) +else: + fig, ax = plt.subplots(1, 1, figsize=(5,5)) + +def scale(x): + return 2.**(10*x) - 1. + +if args.score == 'svd': + score_scale = lambda x: 10.0**x +else: + score_scale = lambda x: x + +if args.nasspace == 'nonetwork': + ax.scatter(scale(accs/100.), score_scale(scores), c=newcmp(accs/100., depths)) +else: + ax.scatter(scale(accs/100. if args.nasspace == 'nasbench201' or 'nds' in args.nasspace else accs), score_scale(scores), c=newcmp(accs/100. if args.nasspace == 'nasbench201' or 'nds' in args.nasspace else accs)) + + +if args.dataset == 'cifar100': + ax.set_xticks([scale(float(a)/100.) for a in [40, 60, 70]]) + ax.set_xticklabels([f'{a}' for a in [40, 60, 70]]) +elif args.dataset == 'imagenette2': + ax.set_xticks([scale(float(a)/100.) for a in [40, 50, 60, 70]]) + ax.set_xticklabels([f'{a}' for a in [40, 50, 60, 70]]) +elif args.dataset == 'ImageNet16-120': + ax.set_xticks([scale(float(a)/100.) for a in [20, 30, 40, 45]]) + ax.set_xticklabels([f'{a}' for a in [20, 30, 40, 45]]) +elif args.nasspace == 'nasbench101' and args.dataset == 'cifar10': + ax.set_xticks([scale(float(a)/100.) for a in [50, 80, 90, 95]]) + ax.set_xticklabels([f'{a}' for a in [50, 80, 90, 95]]) +elif args.nasspace == 'nasbench201' and args.dataset == 'cifar10' and args.score == 'svd': + ax.set_xticks([scale(float(a)/100.) for a in [50, 80, 90, 95]]) + ax.set_xticklabels([f'{a}' for a in [50, 80, 90, 95]]) +elif 'nds_resne' in args.nasspace and args.dataset == 'cifar10': + ax.set_xticks([scale(float(a)/100.) for a in [85, 88, 91, 94]]) + ax.set_xticklabels([f'{a}' for a in [85, 88, 91, 94]]) +elif args.nasspace == 'nds_darts' and args.dataset == 'cifar10': + ax.set_xticks([scale(float(a)/100.) for a in [80, 85, 90, 95]]) + ax.set_xticklabels([f'{a}' for a in [80, 85, 90, 95]]) +elif args.nasspace == 'nds_pnas' and args.dataset == 'cifar10': + ax.set_xticks([scale(float(a)/100.) for a in [90., 91.5, 93, 94.5]]) + ax.set_xticklabels([f'{a}' for a in [90., 91.5, 93, 94.5]]) +else: + ax.set_xticks([scale(float(a)/100.) for a in [50, 80, 90]]) + ax.set_xticklabels([f'{a}' for a in [50, 80, 90]]) +ax.spines["top"].set_visible(False) +ax.spines["right"].set_visible(False) + +nasspacenames = { + 'nds_resnext-a_in': 'NDS-ResNeXt-A(ImageNet)', + 'nds_resnext-b_in': 'NDS-ResNeXt-B(ImageNet)', + 'nds_resnext-a': 'NDS-ResNeXt-A(CIFAR10)', + 'nds_resnext-b': 'NDS-ResNeXt-B(CIFAR10)', + 'nds_nasnet': 'NDS-NASNet(CIFAR10)', + 'nds_nasnet_in': 'NDS-NASNet(ImageNet)', + 'nds_enas': 'NDS-ENAS(CIFAR10)', + 'nds_enas_in': 'NDS-ENAS(ImageNet)', + 'nds_amoeba': 'NDS-Amoeba(CIFAR10)', + 'nds_amoeba_in': 'NDS-Amoeba(ImageNet)', + 'nds_resnet': 'NDS-ResNet(CIFAR10)', + 'nds_pnas': 'NDS-PNAS(CIFAR10)', + 'nds_pnas_in': 'NDS-PNAS(ImageNet)', + 'nds_darts': 'NDS-DARTS(CIFAR10)', + 'nds_darts_in': 'NDS-DARTS(ImageNet)', + 'nds_darts_fix-w-d': 'NDS-DARTS fixed width/depth (CIFAR10)', + 'nds_darts_in_fix-w-d': 'NDS-DARTS fixed width/depth (ImageNet)', + 'nds_darts_in': 'NDS-DARTS(ImageNet)', + 'nasbench101': 'NAS-Bench-101', + 'nasbench201': 'NAS-Bench-201' +} + +ax.set_ylabel('Score') +ax.set_xlabel(f'{"Test" if not args.trainval else "Validation"} accuracy') +ax.set_title(f'{nasspacenames[args.nasspace]} {args.dataset} \n $\\tau=${tau:.3f}') + +filename = f'{args.save_loc}/{args.save_string}_{args.score}_{args.nasspace}_{args.dataset}{"_" + args.init + "_" if args.init != "" else args.init}{"_dropout" if args.dropout else ""}_{args.augtype}_{args.sigma}_{args.repeat}_{args.trainval}_{args.batch_size}_{args.maxofn}_{args.seed}' +print(filename) +plt.tight_layout() +plt.savefig(filename + '.pdf') +plt.savefig(filename + '.png') + +plt.show() diff --git a/process_results.py b/process_results.py deleted file mode 100644 index a0e880c..0000000 --- a/process_results.py +++ /dev/null @@ -1,87 +0,0 @@ -import numpy as np -import argparse -import os -import random -import pandas as pd -from collections import OrderedDict - -import tabulate -parser = argparse.ArgumentParser(description='Produce tables') -parser.add_argument('--data_loc', default='../datasets/cifar/', type=str, help='dataset folder') -parser.add_argument('--save_loc', default='results', type=str, help='folder to save results') - -parser.add_argument('--batch_size', default=256, type=int) -parser.add_argument('--GPU', default='0', type=str) - -parser.add_argument('--seed', default=1, type=int) -parser.add_argument('--trainval', action='store_true') - -parser.add_argument('--n_runs', default=500, type=int) - -args = parser.parse_args() -os.environ['CUDA_VISIBLE_DEVICES'] = args.GPU - -from statistics import mean, median, stdev as std - -import torch - -torch.backends.cudnn.deterministic = True -torch.backends.cudnn.benchmark = False -random.seed(args.seed) -np.random.seed(args.seed) -torch.manual_seed(args.seed) - -df = [] - -datasets = OrderedDict() - -datasets['CIFAR-10 (val)'] = ('cifar10-valid', 'x-valid', True) -datasets['CIFAR-10 (test)'] = ('cifar10', 'ori-test', False) - -### CIFAR-100 -datasets['CIFAR-100 (val)'] = ('cifar100', 'x-valid', False) -datasets['CIFAR-100 (test)'] = ('cifar100', 'x-test', False) - -datasets['ImageNet16-120 (val)'] = ('ImageNet16-120', 'x-valid', False) -datasets['ImageNet16-120 (test)'] = ('ImageNet16-120', 'x-test', False) - - -dataset_top1s = OrderedDict() - -for n_samples in [10, 100]: - method = f"Ours (N={n_samples})" - - time = 0. - - for dataset, params in datasets.items(): - top1s = [] - - dset = params[0] - acc_type = 'accs' if 'test' in params[1] else 'val_accs' - filename = f"{args.save_loc}/{dset}_{args.n_runs}_{n_samples}_{args.seed}.t7" - - full_scores = torch.load(filename) - if dataset == 'CIFAR-10 (test)': - time = median(full_scores['times']) - time = f"{time:.2f}" - accs = [] - for n in range(args.n_runs): - acc = full_scores[acc_type][n] - accs.append(acc) - dataset_top1s[dataset] = accs - - cifar10_val = f"{mean(dataset_top1s['CIFAR-10 (val)']):.2f} +- {std(dataset_top1s['CIFAR-10 (val)']):.2f}" - cifar10_test = f"{mean(dataset_top1s['CIFAR-10 (test)']):.2f} +- {std(dataset_top1s['CIFAR-10 (test)']):.2f}" - - cifar100_val = f"{mean(dataset_top1s['CIFAR-100 (val)']):.2f} +- {std(dataset_top1s['CIFAR-100 (val)']):.2f}" - cifar100_test = f"{mean(dataset_top1s['CIFAR-100 (test)']):.2f} +- {std(dataset_top1s['CIFAR-100 (test)']):.2f}" - - imagenet_val = f"{mean(dataset_top1s['ImageNet16-120 (val)']):.2f} +- {std(dataset_top1s['ImageNet16-120 (val)']):.2f}" - imagenet_test = f"{mean(dataset_top1s['ImageNet16-120 (test)']):.2f} +- {std(dataset_top1s['ImageNet16-120 (test)']):.2f}" - - df.append([method, time, cifar10_val, cifar10_test, cifar100_val, cifar100_test, imagenet_val, imagenet_test]) - - -df = pd.DataFrame(df, columns=['Method','Search time (s)','CIFAR-10 (val)','CIFAR-10 (test)','CIFAR-100 (val)','CIFAR-100 (test)','ImageNet16-120 (val)','ImageNet16-120 (test)' ]) - -print(tabulate.tabulate(df.values,df.columns, tablefmt="pipe")) diff --git a/pycls/core/__init__.py b/pycls/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pycls/core/benchmark.py b/pycls/core/benchmark.py new file mode 100644 index 0000000..b07c892 --- /dev/null +++ b/pycls/core/benchmark.py @@ -0,0 +1,136 @@ +#!/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. + +"""Benchmarking functions.""" + +import pycls.core.logging as logging +import pycls.datasets.loader as loader +import torch +from pycls.core.config import cfg +from pycls.core.timer import Timer + + +logger = logging.get_logger(__name__) + + +@torch.no_grad() +def compute_time_eval(model): + """Computes precise model forward test time using dummy data.""" + # Use eval mode + model.eval() + # Generate a dummy mini-batch and copy data to GPU + im_size, batch_size = cfg.TRAIN.IM_SIZE, int(cfg.TEST.BATCH_SIZE / cfg.NUM_GPUS) + if cfg.TASK == "jig": + inputs = torch.rand(batch_size, cfg.JIGSAW_GRID ** 2, cfg.MODEL.INPUT_CHANNELS, im_size, im_size).cuda(non_blocking=False) + else: + inputs = torch.zeros(batch_size, cfg.MODEL.INPUT_CHANNELS, im_size, im_size).cuda(non_blocking=False) + # Compute precise forward pass time + timer = Timer() + total_iter = cfg.PREC_TIME.NUM_ITER + cfg.PREC_TIME.WARMUP_ITER + for cur_iter in range(total_iter): + # Reset the timers after the warmup phase + if cur_iter == cfg.PREC_TIME.WARMUP_ITER: + timer.reset() + # Forward + timer.tic() + model(inputs) + torch.cuda.synchronize() + timer.toc() + return timer.average_time + + +def compute_time_train(model, loss_fun): + """Computes precise model forward + backward time using dummy data.""" + # Use train mode + model.train() + # Generate a dummy mini-batch and copy data to GPU + im_size, batch_size = cfg.TRAIN.IM_SIZE, int(cfg.TRAIN.BATCH_SIZE / cfg.NUM_GPUS) + if cfg.TASK == "jig": + inputs = torch.rand(batch_size, cfg.JIGSAW_GRID ** 2, cfg.MODEL.INPUT_CHANNELS, im_size, im_size).cuda(non_blocking=False) + else: + inputs = torch.rand(batch_size, cfg.MODEL.INPUT_CHANNELS, im_size, im_size).cuda(non_blocking=False) + if cfg.TASK in ['col', 'seg']: + labels = torch.zeros(batch_size, im_size, im_size, dtype=torch.int64).cuda(non_blocking=False) + else: + labels = torch.zeros(batch_size, dtype=torch.int64).cuda(non_blocking=False) + # Cache BatchNorm2D running stats + bns = [m for m in model.modules() if isinstance(m, torch.nn.BatchNorm2d)] + bn_stats = [[bn.running_mean.clone(), bn.running_var.clone()] for bn in bns] + # Compute precise forward backward pass time + fw_timer, bw_timer = Timer(), Timer() + total_iter = cfg.PREC_TIME.NUM_ITER + cfg.PREC_TIME.WARMUP_ITER + for cur_iter in range(total_iter): + # Reset the timers after the warmup phase + if cur_iter == cfg.PREC_TIME.WARMUP_ITER: + fw_timer.reset() + bw_timer.reset() + # Forward + fw_timer.tic() + preds = model(inputs) + if isinstance(preds, tuple): + loss = loss_fun(preds[0], labels) + cfg.NAS.AUX_WEIGHT * loss_fun(preds[1], labels) + preds = preds[0] + else: + loss = loss_fun(preds, labels) + torch.cuda.synchronize() + fw_timer.toc() + # Backward + bw_timer.tic() + loss.backward() + torch.cuda.synchronize() + bw_timer.toc() + # Restore BatchNorm2D running stats + for bn, (mean, var) in zip(bns, bn_stats): + bn.running_mean, bn.running_var = mean, var + return fw_timer.average_time, bw_timer.average_time + + +def compute_time_loader(data_loader): + """Computes loader time.""" + timer = Timer() + loader.shuffle(data_loader, 0) + data_loader_iterator = iter(data_loader) + total_iter = cfg.PREC_TIME.NUM_ITER + cfg.PREC_TIME.WARMUP_ITER + total_iter = min(total_iter, len(data_loader)) + for cur_iter in range(total_iter): + if cur_iter == cfg.PREC_TIME.WARMUP_ITER: + timer.reset() + timer.tic() + next(data_loader_iterator) + timer.toc() + return timer.average_time + + +def compute_time_full(model, loss_fun, train_loader, test_loader): + """Times model and data loader.""" + logger.info("Computing model and loader timings...") + # Compute timings + test_fw_time = compute_time_eval(model) + train_fw_time, train_bw_time = compute_time_train(model, loss_fun) + train_fw_bw_time = train_fw_time + train_bw_time + train_loader_time = compute_time_loader(train_loader) + # Output iter timing + iter_times = { + "test_fw_time": test_fw_time, + "train_fw_time": train_fw_time, + "train_bw_time": train_bw_time, + "train_fw_bw_time": train_fw_bw_time, + "train_loader_time": train_loader_time, + } + logger.info(logging.dump_log_data(iter_times, "iter_times")) + # Output epoch timing + epoch_times = { + "test_fw_time": test_fw_time * len(test_loader), + "train_fw_time": train_fw_time * len(train_loader), + "train_bw_time": train_bw_time * len(train_loader), + "train_fw_bw_time": train_fw_bw_time * len(train_loader), + "train_loader_time": train_loader_time * len(train_loader), + } + logger.info(logging.dump_log_data(epoch_times, "epoch_times")) + # Compute data loader overhead (assuming DATA_LOADER.NUM_WORKERS>1) + overhead = max(0, train_loader_time - train_fw_bw_time) / train_fw_bw_time + logger.info("Overhead of data loader is {:.2f}%".format(overhead * 100)) diff --git a/pycls/core/builders.py b/pycls/core/builders.py new file mode 100644 index 0000000..bdf0778 --- /dev/null +++ b/pycls/core/builders.py @@ -0,0 +1,88 @@ +#!/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. + +"""Model and loss construction functions.""" + +import torch +from pycls.core.config import cfg +from pycls.models.anynet import AnyNet +from pycls.models.effnet import EffNet +from pycls.models.regnet import RegNet +from pycls.models.resnet import ResNet +from pycls.models.nas.nas import NAS +from pycls.models.nas.nas_search import NAS_Search +from pycls.models.nas_bench.model_builder import NAS_Bench + + +class LabelSmoothedCrossEntropyLoss(torch.nn.Module): + """CrossEntropyLoss with label smoothing.""" + def __init__(self): + super(LabelSmoothedCrossEntropyLoss, self).__init__() + self.eps = cfg.MODEL.LABEL_SMOOTHING_EPS + self.num_classes = cfg.MODEL.NUM_CLASSES + + def forward(self, logits, target): + pred = logits.log_softmax(dim=-1) + with torch.no_grad(): + target_dist = torch.ones_like(pred) * self.eps / (self.num_classes - 1) + target_dist.scatter_(-1, target.unsqueeze(-1), 1 - self.eps) + return (-target_dist * pred).sum(dim=-1).mean() + + +# Supported models +_models = { + "anynet": AnyNet, + "effnet": EffNet, + "resnet": ResNet, + "regnet": RegNet, + "nas": NAS, + "nas_search": NAS_Search, + "nas_bench": NAS_Bench, +} + +# Supported loss functions +_loss_funs = { + "cross_entropy": torch.nn.CrossEntropyLoss, + "label_smoothed_cross_entropy": LabelSmoothedCrossEntropyLoss, +} + + +def get_model(): + """Gets the model class specified in the config.""" + err_str = "Model type '{}' not supported" + assert cfg.MODEL.TYPE in _models.keys(), err_str.format(cfg.MODEL.TYPE) + return _models[cfg.MODEL.TYPE] + + +def get_loss_fun(): + """Gets the loss function class specified in the config.""" + err_str = "Loss function type '{}' not supported" + assert cfg.MODEL.LOSS_FUN in _loss_funs.keys(), err_str.format(cfg.TRAIN.LOSS) + return _loss_funs[cfg.MODEL.LOSS_FUN] + + +def build_model(): + """Builds the model.""" + return get_model()() + + +def build_loss_fun(): + """Build the loss function.""" + if cfg.TASK == "seg": + return get_loss_fun()(ignore_index=255) + else: + return get_loss_fun()() + + +def register_model(name, ctor): + """Registers a model dynamically.""" + _models[name] = ctor + + +def register_loss_fun(name, ctor): + """Registers a loss function dynamically.""" + _loss_funs[name] = ctor diff --git a/pycls/core/checkpoint.py b/pycls/core/checkpoint.py new file mode 100644 index 0000000..06bca15 --- /dev/null +++ b/pycls/core/checkpoint.py @@ -0,0 +1,98 @@ +#!/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. + +"""Functions that handle saving and loading of checkpoints.""" + +import os + +import pycls.core.distributed as dist +import torch +from pycls.core.config import cfg + + +# Common prefix for checkpoint file names +_NAME_PREFIX = "model_epoch_" +# Checkpoints directory name +_DIR_NAME = "checkpoints" + + +def get_checkpoint_dir(): + """Retrieves the location for storing checkpoints.""" + return os.path.join(cfg.OUT_DIR, _DIR_NAME) + + +def get_checkpoint(epoch): + """Retrieves the path to a checkpoint file.""" + name = "{}{:04d}.pyth".format(_NAME_PREFIX, epoch) + return os.path.join(get_checkpoint_dir(), name) + + +def get_last_checkpoint(): + """Retrieves the most recent checkpoint (highest epoch number).""" + checkpoint_dir = get_checkpoint_dir() + # Checkpoint file names are in lexicographic order + checkpoints = [f for f in os.listdir(checkpoint_dir) if _NAME_PREFIX in f] + last_checkpoint_name = sorted(checkpoints)[-1] + return os.path.join(checkpoint_dir, last_checkpoint_name) + + +def has_checkpoint(): + """Determines if there are checkpoints available.""" + checkpoint_dir = get_checkpoint_dir() + if not os.path.exists(checkpoint_dir): + return False + return any(_NAME_PREFIX in f for f in os.listdir(checkpoint_dir)) + + +def save_checkpoint(model, optimizer, epoch): + """Saves a checkpoint.""" + # Save checkpoints only from the master process + if not dist.is_master_proc(): + return + # Ensure that the checkpoint dir exists + os.makedirs(get_checkpoint_dir(), exist_ok=True) + # Omit the DDP wrapper in the multi-gpu setting + sd = model.module.state_dict() if cfg.NUM_GPUS > 1 else model.state_dict() + # Record the state + if isinstance(optimizer, list): + checkpoint = { + "epoch": epoch, + "model_state": sd, + "optimizer_w_state": optimizer[0].state_dict(), + "optimizer_a_state": optimizer[1].state_dict(), + "cfg": cfg.dump(), + } + else: + checkpoint = { + "epoch": epoch, + "model_state": sd, + "optimizer_state": optimizer.state_dict(), + "cfg": cfg.dump(), + } + # Write the checkpoint + checkpoint_file = get_checkpoint(epoch + 1) + torch.save(checkpoint, checkpoint_file) + return checkpoint_file + + +def load_checkpoint(checkpoint_file, model, optimizer=None): + """Loads the checkpoint from the given file.""" + err_str = "Checkpoint '{}' not found" + assert os.path.exists(checkpoint_file), err_str.format(checkpoint_file) + # Load the checkpoint on CPU to avoid GPU mem spike + checkpoint = torch.load(checkpoint_file, map_location="cpu") + # Account for the DDP wrapper in the multi-gpu setting + ms = model.module if cfg.NUM_GPUS > 1 else model + ms.load_state_dict(checkpoint["model_state"]) + # Load the optimizer state (commonly not done when fine-tuning) + if optimizer: + if isinstance(optimizer, list): + optimizer[0].load_state_dict(checkpoint["optimizer_w_state"]) + optimizer[1].load_state_dict(checkpoint["optimizer_a_state"]) + else: + optimizer.load_state_dict(checkpoint["optimizer_state"]) + return checkpoint["epoch"] diff --git a/pycls/core/config.py b/pycls/core/config.py new file mode 100644 index 0000000..cb28145 --- /dev/null +++ b/pycls/core/config.py @@ -0,0 +1,500 @@ +#!/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. + +"""Configuration file (powered by YACS).""" + +import argparse +import os +import sys + +from pycls.core.io import cache_url +from yacs.config import CfgNode as CfgNode + + +# Global config object +_C = CfgNode() + +# Example usage: +# from core.config import cfg +cfg = _C + + +# ------------------------------------------------------------------------------------ # +# Model options +# ------------------------------------------------------------------------------------ # +_C.MODEL = CfgNode() + +# Model type +_C.MODEL.TYPE = "" + +# Number of weight layers +_C.MODEL.DEPTH = 0 + +# Number of input channels +_C.MODEL.INPUT_CHANNELS = 3 + +# Number of classes +_C.MODEL.NUM_CLASSES = 10 + +# Loss function (see pycls/core/builders.py for options) +_C.MODEL.LOSS_FUN = "cross_entropy" + +# Label smoothing eps +_C.MODEL.LABEL_SMOOTHING_EPS = 0.0 + +# ASPP channels +_C.MODEL.ASPP_CHANNELS = 256 + +# ASPP dilation rates +_C.MODEL.ASPP_RATES = [6, 12, 18] + + +# ------------------------------------------------------------------------------------ # +# ResNet options +# ------------------------------------------------------------------------------------ # +_C.RESNET = CfgNode() + +# Transformation function (see pycls/models/resnet.py for options) +_C.RESNET.TRANS_FUN = "basic_transform" + +# Number of groups to use (1 -> ResNet; > 1 -> ResNeXt) +_C.RESNET.NUM_GROUPS = 1 + +# Width of each group (64 -> ResNet; 4 -> ResNeXt) +_C.RESNET.WIDTH_PER_GROUP = 64 + +# Apply stride to 1x1 conv (True -> MSRA; False -> fb.torch) +_C.RESNET.STRIDE_1X1 = True + + +# ------------------------------------------------------------------------------------ # +# AnyNet options +# ------------------------------------------------------------------------------------ # +_C.ANYNET = CfgNode() + +# Stem type +_C.ANYNET.STEM_TYPE = "simple_stem_in" + +# Stem width +_C.ANYNET.STEM_W = 32 + +# Block type +_C.ANYNET.BLOCK_TYPE = "res_bottleneck_block" + +# Depth for each stage (number of blocks in the stage) +_C.ANYNET.DEPTHS = [] + +# Width for each stage (width of each block in the stage) +_C.ANYNET.WIDTHS = [] + +# Strides for each stage (applies to the first block of each stage) +_C.ANYNET.STRIDES = [] + +# Bottleneck multipliers for each stage (applies to bottleneck block) +_C.ANYNET.BOT_MULS = [] + +# Group widths for each stage (applies to bottleneck block) +_C.ANYNET.GROUP_WS = [] + +# Whether SE is enabled for res_bottleneck_block +_C.ANYNET.SE_ON = False + +# SE ratio +_C.ANYNET.SE_R = 0.25 + + +# ------------------------------------------------------------------------------------ # +# RegNet options +# ------------------------------------------------------------------------------------ # +_C.REGNET = CfgNode() + +# Stem type +_C.REGNET.STEM_TYPE = "simple_stem_in" + +# Stem width +_C.REGNET.STEM_W = 32 + +# Block type +_C.REGNET.BLOCK_TYPE = "res_bottleneck_block" + +# Stride of each stage +_C.REGNET.STRIDE = 2 + +# Squeeze-and-Excitation (RegNetY) +_C.REGNET.SE_ON = False +_C.REGNET.SE_R = 0.25 + +# Depth +_C.REGNET.DEPTH = 10 + +# Initial width +_C.REGNET.W0 = 32 + +# Slope +_C.REGNET.WA = 5.0 + +# Quantization +_C.REGNET.WM = 2.5 + +# Group width +_C.REGNET.GROUP_W = 16 + +# Bottleneck multiplier (bm = 1 / b from the paper) +_C.REGNET.BOT_MUL = 1.0 + + +# ------------------------------------------------------------------------------------ # +# EfficientNet options +# ------------------------------------------------------------------------------------ # +_C.EN = CfgNode() + +# Stem width +_C.EN.STEM_W = 32 + +# Depth for each stage (number of blocks in the stage) +_C.EN.DEPTHS = [] + +# Width for each stage (width of each block in the stage) +_C.EN.WIDTHS = [] + +# Expansion ratios for MBConv blocks in each stage +_C.EN.EXP_RATIOS = [] + +# Squeeze-and-Excitation (SE) ratio +_C.EN.SE_R = 0.25 + +# Strides for each stage (applies to the first block of each stage) +_C.EN.STRIDES = [] + +# Kernel sizes for each stage +_C.EN.KERNELS = [] + +# Head width +_C.EN.HEAD_W = 1280 + +# Drop connect ratio +_C.EN.DC_RATIO = 0.0 + +# Dropout ratio +_C.EN.DROPOUT_RATIO = 0.0 + + +# ---------------------------------------------------------------------------- # +# NAS options +# ---------------------------------------------------------------------------- # +_C.NAS = CfgNode() + +# Cell genotype +_C.NAS.GENOTYPE = 'nas' + +# Custom genotype +_C.NAS.CUSTOM_GENOTYPE = [] + +# Base NAS width +_C.NAS.WIDTH = 16 + +# Total number of cells +_C.NAS.DEPTH = 20 + +# Auxiliary heads +_C.NAS.AUX = False + +# Weight for auxiliary heads +_C.NAS.AUX_WEIGHT = 0.4 + +# Drop path probability +_C.NAS.DROP_PROB = 0.0 + +# Matrix in NAS Bench +_C.NAS.MATRIX = [] + +# Operations in NAS Bench +_C.NAS.OPS = [] + +# Number of stacks in NAS Bench +_C.NAS.NUM_STACKS = 3 + +# Number of modules per stack in NAS Bench +_C.NAS.NUM_MODULES_PER_STACK = 3 + + +# ------------------------------------------------------------------------------------ # +# Batch norm options +# ------------------------------------------------------------------------------------ # +_C.BN = CfgNode() + +# BN epsilon +_C.BN.EPS = 1e-5 + +# BN momentum (BN momentum in PyTorch = 1 - BN momentum in Caffe2) +_C.BN.MOM = 0.1 + +# Precise BN stats +_C.BN.USE_PRECISE_STATS = False +_C.BN.NUM_SAMPLES_PRECISE = 1024 + +# Initialize the gamma of the final BN of each block to zero +_C.BN.ZERO_INIT_FINAL_GAMMA = False + +# Use a different weight decay for BN layers +_C.BN.USE_CUSTOM_WEIGHT_DECAY = False +_C.BN.CUSTOM_WEIGHT_DECAY = 0.0 + + +# ------------------------------------------------------------------------------------ # +# Optimizer options +# ------------------------------------------------------------------------------------ # +_C.OPTIM = CfgNode() + +# Base learning rate +_C.OPTIM.BASE_LR = 0.1 + +# Learning rate policy select from {'cos', 'exp', 'steps'} +_C.OPTIM.LR_POLICY = "cos" + +# Exponential decay factor +_C.OPTIM.GAMMA = 0.1 + +# Steps for 'steps' policy (in epochs) +_C.OPTIM.STEPS = [] + +# Learning rate multiplier for 'steps' policy +_C.OPTIM.LR_MULT = 0.1 + +# Maximal number of epochs +_C.OPTIM.MAX_EPOCH = 200 + +# Momentum +_C.OPTIM.MOMENTUM = 0.9 + +# Momentum dampening +_C.OPTIM.DAMPENING = 0.0 + +# Nesterov momentum +_C.OPTIM.NESTEROV = True + +# L2 regularization +_C.OPTIM.WEIGHT_DECAY = 5e-4 + +# Start the warm up from OPTIM.BASE_LR * OPTIM.WARMUP_FACTOR +_C.OPTIM.WARMUP_FACTOR = 0.1 + +# Gradually warm up the OPTIM.BASE_LR over this number of epochs +_C.OPTIM.WARMUP_EPOCHS = 0 + +# Update the learning rate per iter +_C.OPTIM.ITER_LR = False + +# Base learning rate for arch +_C.OPTIM.ARCH_BASE_LR = 0.0003 + +# L2 regularization for arch +_C.OPTIM.ARCH_WEIGHT_DECAY = 0.001 + +# Optimizer for arch +_C.OPTIM.ARCH_OPTIM = 'adam' + +# Epoch to start optimizing arch +_C.OPTIM.ARCH_EPOCH = 0.0 + + +# ------------------------------------------------------------------------------------ # +# Training options +# ------------------------------------------------------------------------------------ # +_C.TRAIN = CfgNode() + +# Dataset and split +_C.TRAIN.DATASET = "" +_C.TRAIN.SPLIT = "train" + +# Total mini-batch size +_C.TRAIN.BATCH_SIZE = 128 + +# Image size +_C.TRAIN.IM_SIZE = 224 + +# Evaluate model on test data every eval period epochs +_C.TRAIN.EVAL_PERIOD = 1 + +# Save model checkpoint every checkpoint period epochs +_C.TRAIN.CHECKPOINT_PERIOD = 1 + +# Resume training from the latest checkpoint in the output directory +_C.TRAIN.AUTO_RESUME = True + +# Weights to start training from +_C.TRAIN.WEIGHTS = "" + +# Percentage of gray images in jig +_C.TRAIN.GRAY_PERCENTAGE = 0.0 + +# Portion to create trainA/trainB split +_C.TRAIN.PORTION = 1.0 + + +# ------------------------------------------------------------------------------------ # +# Testing options +# ------------------------------------------------------------------------------------ # +_C.TEST = CfgNode() + +# Dataset and split +_C.TEST.DATASET = "" +_C.TEST.SPLIT = "val" + +# Total mini-batch size +_C.TEST.BATCH_SIZE = 200 + +# Image size +_C.TEST.IM_SIZE = 256 + +# Weights to use for testing +_C.TEST.WEIGHTS = "" + + +# ------------------------------------------------------------------------------------ # +# Common train/test data loader options +# ------------------------------------------------------------------------------------ # +_C.DATA_LOADER = CfgNode() + +# Number of data loader workers per process +_C.DATA_LOADER.NUM_WORKERS = 8 + +# Load data to pinned host memory +_C.DATA_LOADER.PIN_MEMORY = True + + +# ------------------------------------------------------------------------------------ # +# Memory options +# ------------------------------------------------------------------------------------ # +_C.MEM = CfgNode() + +# Perform ReLU inplace +_C.MEM.RELU_INPLACE = True + + +# ------------------------------------------------------------------------------------ # +# CUDNN options +# ------------------------------------------------------------------------------------ # +_C.CUDNN = CfgNode() + +# Perform benchmarking to select the fastest CUDNN algorithms to use +# Note that this may increase the memory usage and will likely not result +# in overall speedups when variable size inputs are used (e.g. COCO training) +_C.CUDNN.BENCHMARK = True + + +# ------------------------------------------------------------------------------------ # +# Precise timing options +# ------------------------------------------------------------------------------------ # +_C.PREC_TIME = CfgNode() + +# Number of iterations to warm up the caches +_C.PREC_TIME.WARMUP_ITER = 3 + +# Number of iterations to compute avg time +_C.PREC_TIME.NUM_ITER = 30 + + +# ------------------------------------------------------------------------------------ # +# Misc options +# ------------------------------------------------------------------------------------ # + +# Number of GPUs to use (applies to both training and testing) +_C.NUM_GPUS = 1 + +# Task (cls, seg, rot, col, jig) +_C.TASK = "cls" + +# Grid in Jigsaw (2, 3); no effect if TASK is not jig +_C.JIGSAW_GRID = 3 + +# Output directory +_C.OUT_DIR = "/tmp" + +# Config destination (in OUT_DIR) +_C.CFG_DEST = "config.yaml" + +# Note that non-determinism may still be present due to non-deterministic +# operator implementations in GPU operator libraries +_C.RNG_SEED = 1 + +# Log destination ('stdout' or 'file') +_C.LOG_DEST = "stdout" + +# Log period in iters +_C.LOG_PERIOD = 10 + +# Distributed backend +_C.DIST_BACKEND = "nccl" + +# Hostname and port for initializing multi-process groups +_C.HOST = "localhost" +_C.PORT = 10001 + +# Models weights referred to by URL are downloaded to this local cache +_C.DOWNLOAD_CACHE = "/tmp/pycls-download-cache" + + +# ------------------------------------------------------------------------------------ # +# Deprecated keys +# ------------------------------------------------------------------------------------ # + +_C.register_deprecated_key("PREC_TIME.BATCH_SIZE") +_C.register_deprecated_key("PREC_TIME.ENABLED") + + +def assert_and_infer_cfg(cache_urls=True): + """Checks config values invariants.""" + err_str = "The first lr step must start at 0" + assert not _C.OPTIM.STEPS or _C.OPTIM.STEPS[0] == 0, err_str + data_splits = ["train", "val", "test"] + err_str = "Data split '{}' not supported" + assert _C.TRAIN.SPLIT in data_splits, err_str.format(_C.TRAIN.SPLIT) + assert _C.TEST.SPLIT in data_splits, err_str.format(_C.TEST.SPLIT) + err_str = "Mini-batch size should be a multiple of NUM_GPUS." + assert _C.TRAIN.BATCH_SIZE % _C.NUM_GPUS == 0, err_str + assert _C.TEST.BATCH_SIZE % _C.NUM_GPUS == 0, err_str + err_str = "Precise BN stats computation not verified for > 1 GPU" + assert not _C.BN.USE_PRECISE_STATS or _C.NUM_GPUS == 1, err_str + err_str = "Log destination '{}' not supported" + assert _C.LOG_DEST in ["stdout", "file"], err_str.format(_C.LOG_DEST) + if cache_urls: + cache_cfg_urls() + + +def cache_cfg_urls(): + """Download URLs in config, cache them, and rewrite cfg to use cached file.""" + _C.TRAIN.WEIGHTS = cache_url(_C.TRAIN.WEIGHTS, _C.DOWNLOAD_CACHE) + _C.TEST.WEIGHTS = cache_url(_C.TEST.WEIGHTS, _C.DOWNLOAD_CACHE) + + +def dump_cfg(): + """Dumps the config to the output directory.""" + cfg_file = os.path.join(_C.OUT_DIR, _C.CFG_DEST) + with open(cfg_file, "w") as f: + _C.dump(stream=f) + + +def load_cfg(out_dir, cfg_dest="config.yaml"): + """Loads config from specified output directory.""" + cfg_file = os.path.join(out_dir, cfg_dest) + _C.merge_from_file(cfg_file) + + +def load_cfg_fom_args(description="Config file options."): + """Load config from command line arguments and set any specified options.""" + parser = argparse.ArgumentParser(description=description) + help_s = "Config file location" + parser.add_argument("--cfg", dest="cfg_file", help=help_s, required=True, type=str) + help_s = "See pycls/core/config.py for all options" + parser.add_argument("opts", help=help_s, default=None, nargs=argparse.REMAINDER) + if len(sys.argv) == 1: + parser.print_help() + sys.exit(1) + args = parser.parse_args() + _C.merge_from_file(args.cfg_file) + _C.merge_from_list(args.opts) diff --git a/pycls/core/distributed.py b/pycls/core/distributed.py new file mode 100644 index 0000000..e2dc7db --- /dev/null +++ b/pycls/core/distributed.py @@ -0,0 +1,157 @@ +#!/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. + +"""Distributed helpers.""" + +import multiprocessing +import os +import signal +import threading +import traceback + +import torch +from pycls.core.config import cfg + + +def is_master_proc(): + """Determines if the current process is the master process. + + Master process is responsible for logging, writing and loading checkpoints. In + the multi GPU setting, we assign the master role to the rank 0 process. When + training using a single GPU, there is a single process which is considered master. + """ + return cfg.NUM_GPUS == 1 or torch.distributed.get_rank() == 0 + + +def init_process_group(proc_rank, world_size): + """Initializes the default process group.""" + # Set the GPU to use + torch.cuda.set_device(proc_rank) + # Initialize the process group + torch.distributed.init_process_group( + backend=cfg.DIST_BACKEND, + init_method="tcp://{}:{}".format(cfg.HOST, cfg.PORT), + world_size=world_size, + rank=proc_rank, + ) + + +def destroy_process_group(): + """Destroys the default process group.""" + torch.distributed.destroy_process_group() + + +def scaled_all_reduce(tensors): + """Performs the scaled all_reduce operation on the provided tensors. + + The input tensors are modified in-place. Currently supports only the sum + reduction operator. The reduced values are scaled by the inverse size of the + process group (equivalent to cfg.NUM_GPUS). + """ + # There is no need for reduction in the single-proc case + if cfg.NUM_GPUS == 1: + return tensors + # Queue the reductions + reductions = [] + for tensor in tensors: + reduction = torch.distributed.all_reduce(tensor, async_op=True) + reductions.append(reduction) + # Wait for reductions to finish + for reduction in reductions: + reduction.wait() + # Scale the results + for tensor in tensors: + tensor.mul_(1.0 / cfg.NUM_GPUS) + return tensors + + +class ChildException(Exception): + """Wraps an exception from a child process.""" + + def __init__(self, child_trace): + super(ChildException, self).__init__(child_trace) + + +class ErrorHandler(object): + """Multiprocessing error handler (based on fairseq's). + + Listens for errors in child processes and propagates the tracebacks to the parent. + """ + + def __init__(self, error_queue): + # Shared error queue + self.error_queue = error_queue + # Children processes sharing the error queue + self.children_pids = [] + # Start a thread listening to errors + self.error_listener = threading.Thread(target=self.listen, daemon=True) + self.error_listener.start() + # Register the signal handler + signal.signal(signal.SIGUSR1, self.signal_handler) + + def add_child(self, pid): + """Registers a child process.""" + self.children_pids.append(pid) + + def listen(self): + """Listens for errors in the error queue.""" + # Wait until there is an error in the queue + child_trace = self.error_queue.get() + # Put the error back for the signal handler + self.error_queue.put(child_trace) + # Invoke the signal handler + os.kill(os.getpid(), signal.SIGUSR1) + + def signal_handler(self, _sig_num, _stack_frame): + """Signal handler.""" + # Kill children processes + for pid in self.children_pids: + os.kill(pid, signal.SIGINT) + # Propagate the error from the child process + raise ChildException(self.error_queue.get()) + + +def run(proc_rank, world_size, error_queue, fun, fun_args, fun_kwargs): + """Runs a function from a child process.""" + try: + # Initialize the process group + init_process_group(proc_rank, world_size) + # Run the function + fun(*fun_args, **fun_kwargs) + except KeyboardInterrupt: + # Killed by the parent process + pass + except Exception: + # Propagate exception to the parent process + error_queue.put(traceback.format_exc()) + finally: + # Destroy the process group + destroy_process_group() + + +def multi_proc_run(num_proc, fun, fun_args=(), fun_kwargs=None): + """Runs a function in a multi-proc setting (unless num_proc == 1).""" + # There is no need for multi-proc in the single-proc case + fun_kwargs = fun_kwargs if fun_kwargs else {} + if num_proc == 1: + fun(*fun_args, **fun_kwargs) + return + # Handle errors from training subprocesses + error_queue = multiprocessing.SimpleQueue() + error_handler = ErrorHandler(error_queue) + # Run each training subprocess + ps = [] + for i in range(num_proc): + p_i = multiprocessing.Process( + target=run, args=(i, num_proc, error_queue, fun, fun_args, fun_kwargs) + ) + ps.append(p_i) + p_i.start() + error_handler.add_child(p_i.pid) + # Wait for each subprocess to finish + for p in ps: + p.join() diff --git a/pycls/core/io.py b/pycls/core/io.py new file mode 100644 index 0000000..9f79ffe --- /dev/null +++ b/pycls/core/io.py @@ -0,0 +1,77 @@ +#!/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. + +"""IO utilities (adapted from Detectron)""" + +import logging +import os +import re +import sys +from urllib import request as urlrequest + + +logger = logging.getLogger(__name__) + +_PYCLS_BASE_URL = "https://dl.fbaipublicfiles.com/pycls" + + +def cache_url(url_or_file, cache_dir): + """Download the file specified by the URL to the cache_dir and return the path to + the cached file. If the argument is not a URL, simply return it as is. + """ + is_url = re.match(r"^(?:http)s?://", url_or_file, re.IGNORECASE) is not None + if not is_url: + return url_or_file + url = url_or_file + err_str = "pycls only automatically caches URLs in the pycls S3 bucket: {}" + assert url.startswith(_PYCLS_BASE_URL), err_str.format(_PYCLS_BASE_URL) + cache_file_path = url.replace(_PYCLS_BASE_URL, cache_dir) + if os.path.exists(cache_file_path): + return cache_file_path + cache_file_dir = os.path.dirname(cache_file_path) + if not os.path.exists(cache_file_dir): + os.makedirs(cache_file_dir) + logger.info("Downloading remote file {} to {}".format(url, cache_file_path)) + download_url(url, cache_file_path) + return cache_file_path + + +def _progress_bar(count, total): + """Report download progress. Credit: + https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console/27871113 + """ + bar_len = 60 + filled_len = int(round(bar_len * count / float(total))) + percents = round(100.0 * count / float(total), 1) + bar = "=" * filled_len + "-" * (bar_len - filled_len) + sys.stdout.write( + " [{}] {}% of {:.1f}MB file \r".format(bar, percents, total / 1024 / 1024) + ) + sys.stdout.flush() + if count >= total: + sys.stdout.write("\n") + + +def download_url(url, dst_file_path, chunk_size=8192, progress_hook=_progress_bar): + """Download url and write it to dst_file_path. Credit: + https://stackoverflow.com/questions/2028517/python-urllib2-progress-hook + """ + req = urlrequest.Request(url) + response = urlrequest.urlopen(req) + total_size = response.info().get("Content-Length").strip() + total_size = int(total_size) + bytes_so_far = 0 + with open(dst_file_path, "wb") as f: + while 1: + chunk = response.read(chunk_size) + bytes_so_far += len(chunk) + if not chunk: + break + if progress_hook: + progress_hook(bytes_so_far, total_size) + f.write(chunk) + return bytes_so_far diff --git a/pycls/core/logging.py b/pycls/core/logging.py new file mode 100644 index 0000000..31750b2 --- /dev/null +++ b/pycls/core/logging.py @@ -0,0 +1,138 @@ +#!/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. + +"""Logging.""" + +import builtins +import decimal +import logging +import os +import sys + +import pycls.core.distributed as dist +import simplejson +from pycls.core.config import cfg + + +# Show filename and line number in logs +_FORMAT = "[%(filename)s: %(lineno)3d]: %(message)s" + +# Log file name (for cfg.LOG_DEST = 'file') +_LOG_FILE = "stdout.log" + +# Data output with dump_log_data(data, data_type) will be tagged w/ this +_TAG = "json_stats: " + +# Data output with dump_log_data(data, data_type) will have data[_TYPE]=data_type +_TYPE = "_type" + + +def _suppress_print(): + """Suppresses printing from the current process.""" + + def ignore(*_objects, _sep=" ", _end="\n", _file=sys.stdout, _flush=False): + pass + + builtins.print = ignore + + +def setup_logging(): + """Sets up the logging.""" + # Enable logging only for the master process + if dist.is_master_proc(): + # Clear the root logger to prevent any existing logging config + # (e.g. set by another module) from messing with our setup + logging.root.handlers = [] + # Construct logging configuration + logging_config = {"level": logging.INFO, "format": _FORMAT} + # Log either to stdout or to a file + if cfg.LOG_DEST == "stdout": + logging_config["stream"] = sys.stdout + else: + logging_config["filename"] = os.path.join(cfg.OUT_DIR, _LOG_FILE) + # Configure logging + logging.basicConfig(**logging_config) + else: + _suppress_print() + + +def get_logger(name): + """Retrieves the logger.""" + return logging.getLogger(name) + + +def dump_log_data(data, data_type, prec=4): + """Covert data (a dictionary) into tagged json string for logging.""" + data[_TYPE] = data_type + data = float_to_decimal(data, prec) + data_json = simplejson.dumps(data, sort_keys=True, use_decimal=True) + return "{:s}{:s}".format(_TAG, data_json) + + +def float_to_decimal(data, prec=4): + """Convert floats to decimals which allows for fixed width json.""" + if isinstance(data, dict): + return {k: float_to_decimal(v, prec) for k, v in data.items()} + if isinstance(data, float): + return decimal.Decimal(("{:." + str(prec) + "f}").format(data)) + else: + return data + + +def get_log_files(log_dir, name_filter="", log_file=_LOG_FILE): + """Get all log files in directory containing subdirs of trained models.""" + names = [n for n in sorted(os.listdir(log_dir)) if name_filter in n] + files = [os.path.join(log_dir, n, log_file) for n in names] + f_n_ps = [(f, n) for (f, n) in zip(files, names) if os.path.exists(f)] + files, names = zip(*f_n_ps) if f_n_ps else ([], []) + return files, names + + +def load_log_data(log_file, data_types_to_skip=()): + """Loads log data into a dictionary of the form data[data_type][metric][index].""" + # Load log_file + assert os.path.exists(log_file), "Log file not found: {}".format(log_file) + with open(log_file, "r") as f: + lines = f.readlines() + # Extract and parse lines that start with _TAG and have a type specified + lines = [l[l.find(_TAG) + len(_TAG) :] for l in lines if _TAG in l] + lines = [simplejson.loads(l) for l in lines] + lines = [l for l in lines if _TYPE in l and not l[_TYPE] in data_types_to_skip] + # Generate data structure accessed by data[data_type][index][metric] + data_types = [l[_TYPE] for l in lines] + data = {t: [] for t in data_types} + for t, line in zip(data_types, lines): + del line[_TYPE] + data[t].append(line) + # Generate data structure accessed by data[data_type][metric][index] + for t in data: + metrics = sorted(data[t][0].keys()) + err_str = "Inconsistent metrics in log for _type={}: {}".format(t, metrics) + assert all(sorted(d.keys()) == metrics for d in data[t]), err_str + data[t] = {m: [d[m] for d in data[t]] for m in metrics} + return data + + +def sort_log_data(data): + """Sort each data[data_type][metric] by epoch or keep only first instance.""" + for t in data: + if "epoch" in data[t]: + assert "epoch_ind" not in data[t] and "epoch_max" not in data[t] + data[t]["epoch_ind"] = [int(e.split("/")[0]) for e in data[t]["epoch"]] + data[t]["epoch_max"] = [int(e.split("/")[1]) for e in data[t]["epoch"]] + epoch = data[t]["epoch_ind"] + if "iter" in data[t]: + assert "iter_ind" not in data[t] and "iter_max" not in data[t] + data[t]["iter_ind"] = [int(i.split("/")[0]) for i in data[t]["iter"]] + data[t]["iter_max"] = [int(i.split("/")[1]) for i in data[t]["iter"]] + itr = zip(epoch, data[t]["iter_ind"], data[t]["iter_max"]) + epoch = [e + (i_ind - 1) / i_max for e, i_ind, i_max in itr] + for m in data[t]: + data[t][m] = [v for _, v in sorted(zip(epoch, data[t][m]))] + else: + data[t] = {m: d[0] for m, d in data[t].items()} + return data diff --git a/pycls/core/meters.py b/pycls/core/meters.py new file mode 100644 index 0000000..a1aab7d --- /dev/null +++ b/pycls/core/meters.py @@ -0,0 +1,435 @@ +#!/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. + +"""Meters.""" + +from collections import deque + +import numpy as np +import pycls.core.logging as logging +import torch +from pycls.core.config import cfg +from pycls.core.timer import Timer + + +logger = logging.get_logger(__name__) + + +def time_string(seconds): + """Converts time in seconds to a fixed-width string format.""" + days, rem = divmod(int(seconds), 24 * 3600) + hrs, rem = divmod(rem, 3600) + mins, secs = divmod(rem, 60) + return "{0:02},{1:02}:{2:02}:{3:02}".format(days, hrs, mins, secs) + + +def inter_union(preds, labels, num_classes): + _, preds = torch.max(preds, 1) + preds = preds.type(torch.uint8) + 1 + labels = labels.type(torch.uint8) + 1 + preds = preds * (labels > 0).type(torch.uint8) + + inter = preds * (preds == labels).type(torch.uint8) + area_inter = torch.histc(inter.type(torch.int64), bins=num_classes, min=1, max=num_classes) + area_preds = torch.histc(preds.type(torch.int64), bins=num_classes, min=1, max=num_classes) + area_labels = torch.histc(labels.type(torch.int64), bins=num_classes, min=1, max=num_classes) + area_union = area_preds + area_labels - area_inter + + return [area_inter.type(torch.float64) / labels.size(0), area_union.type(torch.float64) / labels.size(0)] + + +def topk_errors(preds, labels, ks): + """Computes the top-k error for each k.""" + err_str = "Batch dim of predictions and labels must match" + assert preds.size(0) == labels.size(0), err_str + # Find the top max_k predictions for each sample + _top_max_k_vals, top_max_k_inds = torch.topk( + preds, max(ks), dim=1, largest=True, sorted=True + ) + # (batch_size, max_k) -> (max_k, batch_size) + top_max_k_inds = top_max_k_inds.t() + # (batch_size, ) -> (max_k, batch_size) + rep_max_k_labels = labels.view(1, -1).expand_as(top_max_k_inds) + # (i, j) = 1 if top i-th prediction for the j-th sample is correct + top_max_k_correct = top_max_k_inds.eq(rep_max_k_labels) + # Compute the number of topk correct predictions for each k + topks_correct = [top_max_k_correct[:k, :].view(-1).float().sum() for k in ks] + return [(1.0 - x / preds.size(0)) * 100.0 for x in topks_correct] + + +def gpu_mem_usage(): + """Computes the GPU memory usage for the current device (MB).""" + mem_usage_bytes = torch.cuda.max_memory_allocated() + return mem_usage_bytes / 1024 / 1024 + + +class ScalarMeter(object): + """Measures a scalar value (adapted from Detectron).""" + + def __init__(self, window_size): + self.deque = deque(maxlen=window_size) + self.total = 0.0 + self.count = 0 + + def reset(self): + self.deque.clear() + self.total = 0.0 + self.count = 0 + + def add_value(self, value): + self.deque.append(value) + self.count += 1 + self.total += value + + def get_win_median(self): + return np.median(self.deque) + + def get_win_avg(self): + return np.mean(self.deque) + + def get_global_avg(self): + return self.total / self.count + + +class TrainMeter(object): + """Measures training stats.""" + + def __init__(self, epoch_iters): + self.epoch_iters = epoch_iters + self.max_iter = cfg.OPTIM.MAX_EPOCH * epoch_iters + self.iter_timer = Timer() + self.loss = ScalarMeter(cfg.LOG_PERIOD) + self.loss_total = 0.0 + self.lr = None + # Current minibatch errors (smoothed over a window) + self.mb_top1_err = ScalarMeter(cfg.LOG_PERIOD) + self.mb_top5_err = ScalarMeter(cfg.LOG_PERIOD) + # Number of misclassified examples + self.num_top1_mis = 0 + self.num_top5_mis = 0 + self.num_samples = 0 + + def reset(self, timer=False): + if timer: + self.iter_timer.reset() + self.loss.reset() + self.loss_total = 0.0 + self.lr = None + self.mb_top1_err.reset() + self.mb_top5_err.reset() + self.num_top1_mis = 0 + self.num_top5_mis = 0 + self.num_samples = 0 + + def iter_tic(self): + self.iter_timer.tic() + + def iter_toc(self): + self.iter_timer.toc() + + def update_stats(self, top1_err, top5_err, loss, lr, mb_size): + # Current minibatch stats + self.mb_top1_err.add_value(top1_err) + self.mb_top5_err.add_value(top5_err) + self.loss.add_value(loss) + self.lr = lr + # Aggregate stats + self.num_top1_mis += top1_err * mb_size + self.num_top5_mis += top5_err * mb_size + self.loss_total += loss * mb_size + self.num_samples += mb_size + + def get_iter_stats(self, cur_epoch, cur_iter): + cur_iter_total = cur_epoch * self.epoch_iters + cur_iter + 1 + eta_sec = self.iter_timer.average_time * (self.max_iter - cur_iter_total) + mem_usage = gpu_mem_usage() + stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "iter": "{}/{}".format(cur_iter + 1, self.epoch_iters), + "time_avg": self.iter_timer.average_time, + "time_diff": self.iter_timer.diff, + "eta": time_string(eta_sec), + "top1_err": self.mb_top1_err.get_win_median(), + "top5_err": self.mb_top5_err.get_win_median(), + "loss": self.loss.get_win_median(), + "lr": self.lr, + "mem": int(np.ceil(mem_usage)), + } + return stats + + def log_iter_stats(self, cur_epoch, cur_iter): + if (cur_iter + 1) % cfg.LOG_PERIOD != 0: + return + stats = self.get_iter_stats(cur_epoch, cur_iter) + logger.info(logging.dump_log_data(stats, "train_iter")) + + def get_epoch_stats(self, cur_epoch): + cur_iter_total = (cur_epoch + 1) * self.epoch_iters + eta_sec = self.iter_timer.average_time * (self.max_iter - cur_iter_total) + mem_usage = gpu_mem_usage() + top1_err = self.num_top1_mis / self.num_samples + top5_err = self.num_top5_mis / self.num_samples + avg_loss = self.loss_total / self.num_samples + stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "time_avg": self.iter_timer.average_time, + "eta": time_string(eta_sec), + "top1_err": top1_err, + "top5_err": top5_err, + "loss": avg_loss, + "lr": self.lr, + "mem": int(np.ceil(mem_usage)), + } + return stats + + def log_epoch_stats(self, cur_epoch): + stats = self.get_epoch_stats(cur_epoch) + logger.info(logging.dump_log_data(stats, "train_epoch")) + + +class TestMeter(object): + """Measures testing stats.""" + + def __init__(self, max_iter): + self.max_iter = max_iter + self.iter_timer = Timer() + # Current minibatch errors (smoothed over a window) + self.mb_top1_err = ScalarMeter(cfg.LOG_PERIOD) + self.mb_top5_err = ScalarMeter(cfg.LOG_PERIOD) + # Min errors (over the full test set) + self.min_top1_err = 100.0 + self.min_top5_err = 100.0 + # Number of misclassified examples + self.num_top1_mis = 0 + self.num_top5_mis = 0 + self.num_samples = 0 + + def reset(self, min_errs=False): + if min_errs: + self.min_top1_err = 100.0 + self.min_top5_err = 100.0 + self.iter_timer.reset() + self.mb_top1_err.reset() + self.mb_top5_err.reset() + self.num_top1_mis = 0 + self.num_top5_mis = 0 + self.num_samples = 0 + + def iter_tic(self): + self.iter_timer.tic() + + def iter_toc(self): + self.iter_timer.toc() + + def update_stats(self, top1_err, top5_err, mb_size): + self.mb_top1_err.add_value(top1_err) + self.mb_top5_err.add_value(top5_err) + self.num_top1_mis += top1_err * mb_size + self.num_top5_mis += top5_err * mb_size + self.num_samples += mb_size + + def get_iter_stats(self, cur_epoch, cur_iter): + mem_usage = gpu_mem_usage() + iter_stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "iter": "{}/{}".format(cur_iter + 1, self.max_iter), + "time_avg": self.iter_timer.average_time, + "time_diff": self.iter_timer.diff, + "top1_err": self.mb_top1_err.get_win_median(), + "top5_err": self.mb_top5_err.get_win_median(), + "mem": int(np.ceil(mem_usage)), + } + return iter_stats + + def log_iter_stats(self, cur_epoch, cur_iter): + if (cur_iter + 1) % cfg.LOG_PERIOD != 0: + return + stats = self.get_iter_stats(cur_epoch, cur_iter) + logger.info(logging.dump_log_data(stats, "test_iter")) + + def get_epoch_stats(self, cur_epoch): + top1_err = self.num_top1_mis / self.num_samples + top5_err = self.num_top5_mis / self.num_samples + self.min_top1_err = min(self.min_top1_err, top1_err) + self.min_top5_err = min(self.min_top5_err, top5_err) + mem_usage = gpu_mem_usage() + stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "time_avg": self.iter_timer.average_time, + "top1_err": top1_err, + "top5_err": top5_err, + "min_top1_err": self.min_top1_err, + "min_top5_err": self.min_top5_err, + "mem": int(np.ceil(mem_usage)), + } + return stats + + def log_epoch_stats(self, cur_epoch): + stats = self.get_epoch_stats(cur_epoch) + logger.info(logging.dump_log_data(stats, "test_epoch")) + + +class TrainMeterIoU(object): + """Measures training stats.""" + + def __init__(self, epoch_iters): + self.epoch_iters = epoch_iters + self.max_iter = cfg.OPTIM.MAX_EPOCH * epoch_iters + self.iter_timer = Timer() + self.loss = ScalarMeter(cfg.LOG_PERIOD) + self.loss_total = 0.0 + self.lr = None + + self.mb_miou = ScalarMeter(cfg.LOG_PERIOD) + + self.num_inter = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_union = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_samples = 0 + + def reset(self, timer=False): + if timer: + self.iter_timer.reset() + self.loss.reset() + self.loss_total = 0.0 + self.lr = None + self.mb_miou.reset() + self.num_inter = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_union = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_samples = 0 + + def iter_tic(self): + self.iter_timer.tic() + + def iter_toc(self): + self.iter_timer.toc() + + def update_stats(self, inter, union, loss, lr, mb_size): + # Current minibatch stats + self.mb_miou.add_value((inter / (union + 1e-10)).mean()) + self.loss.add_value(loss) + self.lr = lr + # Aggregate stats + self.num_inter += inter * mb_size + self.num_union += union * mb_size + self.loss_total += loss * mb_size + self.num_samples += mb_size + + def get_iter_stats(self, cur_epoch, cur_iter): + cur_iter_total = cur_epoch * self.epoch_iters + cur_iter + 1 + eta_sec = self.iter_timer.average_time * (self.max_iter - cur_iter_total) + mem_usage = gpu_mem_usage() + stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "iter": "{}/{}".format(cur_iter + 1, self.epoch_iters), + "time_avg": self.iter_timer.average_time, + "time_diff": self.iter_timer.diff, + "eta": time_string(eta_sec), + "miou": self.mb_miou.get_win_median(), + "loss": self.loss.get_win_median(), + "lr": self.lr, + "mem": int(np.ceil(mem_usage)), + } + return stats + + def log_iter_stats(self, cur_epoch, cur_iter): + if (cur_iter + 1) % cfg.LOG_PERIOD != 0: + return + stats = self.get_iter_stats(cur_epoch, cur_iter) + logger.info(logging.dump_log_data(stats, "train_iter")) + + def get_epoch_stats(self, cur_epoch): + cur_iter_total = (cur_epoch + 1) * self.epoch_iters + eta_sec = self.iter_timer.average_time * (self.max_iter - cur_iter_total) + mem_usage = gpu_mem_usage() + miou = (self.num_inter / (self.num_union + 1e-10)).mean() + avg_loss = self.loss_total / self.num_samples + stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "time_avg": self.iter_timer.average_time, + "eta": time_string(eta_sec), + "miou": miou, + "loss": avg_loss, + "lr": self.lr, + "mem": int(np.ceil(mem_usage)), + } + return stats + + def log_epoch_stats(self, cur_epoch): + stats = self.get_epoch_stats(cur_epoch) + logger.info(logging.dump_log_data(stats, "train_epoch")) + + +class TestMeterIoU(object): + """Measures testing stats.""" + + def __init__(self, max_iter): + self.max_iter = max_iter + self.iter_timer = Timer() + + self.mb_miou = ScalarMeter(cfg.LOG_PERIOD) + + self.max_miou = 0.0 + + self.num_inter = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_union = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_samples = 0 + + def reset(self, min_errs=False): + if min_errs: + self.max_miou = 0.0 + self.iter_timer.reset() + self.mb_miou.reset() + self.num_inter = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_union = np.zeros(cfg.MODEL.NUM_CLASSES) + self.num_samples = 0 + + def iter_tic(self): + self.iter_timer.tic() + + def iter_toc(self): + self.iter_timer.toc() + + def update_stats(self, inter, union, mb_size): + self.mb_miou.add_value((inter / (union + 1e-10)).mean()) + self.num_inter += inter * mb_size + self.num_union += union * mb_size + self.num_samples += mb_size + + def get_iter_stats(self, cur_epoch, cur_iter): + mem_usage = gpu_mem_usage() + iter_stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "iter": "{}/{}".format(cur_iter + 1, self.max_iter), + "time_avg": self.iter_timer.average_time, + "time_diff": self.iter_timer.diff, + "miou": self.mb_miou.get_win_median(), + "mem": int(np.ceil(mem_usage)), + } + return iter_stats + + def log_iter_stats(self, cur_epoch, cur_iter): + if (cur_iter + 1) % cfg.LOG_PERIOD != 0: + return + stats = self.get_iter_stats(cur_epoch, cur_iter) + logger.info(logging.dump_log_data(stats, "test_iter")) + + def get_epoch_stats(self, cur_epoch): + miou = (self.num_inter / (self.num_union + 1e-10)).mean() + self.max_miou = max(self.max_miou, miou) + mem_usage = gpu_mem_usage() + stats = { + "epoch": "{}/{}".format(cur_epoch + 1, cfg.OPTIM.MAX_EPOCH), + "time_avg": self.iter_timer.average_time, + "miou": miou, + "max_miou": self.max_miou, + "mem": int(np.ceil(mem_usage)), + } + return stats + + def log_epoch_stats(self, cur_epoch): + stats = self.get_epoch_stats(cur_epoch) + logger.info(logging.dump_log_data(stats, "test_epoch")) diff --git a/pycls/core/net.py b/pycls/core/net.py new file mode 100644 index 0000000..6d18a7f --- /dev/null +++ b/pycls/core/net.py @@ -0,0 +1,129 @@ +#!/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. + +"""Functions for manipulating networks.""" + +import itertools +import math + +import torch +import torch.nn as nn +from pycls.core.config import cfg + + +def init_weights(m): + """Performs ResNet-style weight initialization.""" + if isinstance(m, nn.Conv2d): + # Note that there is no bias due to BN + fan_out = m.kernel_size[0] * m.kernel_size[1] * m.out_channels + m.weight.data.normal_(mean=0.0, std=math.sqrt(2.0 / fan_out)) + elif isinstance(m, nn.BatchNorm2d): + zero_init_gamma = cfg.BN.ZERO_INIT_FINAL_GAMMA + zero_init_gamma = hasattr(m, "final_bn") and m.final_bn and zero_init_gamma + m.weight.data.fill_(0.0 if zero_init_gamma else 1.0) + m.bias.data.zero_() + elif isinstance(m, nn.Linear): + m.weight.data.normal_(mean=0.0, std=0.01) + m.bias.data.zero_() + + +@torch.no_grad() +def compute_precise_bn_stats(model, loader): + """Computes precise BN stats on training data.""" + # Compute the number of minibatches to use + num_iter = min(cfg.BN.NUM_SAMPLES_PRECISE // loader.batch_size, len(loader)) + # Retrieve the BN layers + bns = [m for m in model.modules() if isinstance(m, torch.nn.BatchNorm2d)] + # Initialize stats storage + mus = [torch.zeros_like(bn.running_mean) for bn in bns] + sqs = [torch.zeros_like(bn.running_var) for bn in bns] + # Remember momentum values + moms = [bn.momentum for bn in bns] + # Disable momentum + for bn in bns: + bn.momentum = 1.0 + # Accumulate the stats across the data samples + for inputs, _labels in itertools.islice(loader, num_iter): + model(inputs.cuda()) + # Accumulate the stats for each BN layer + for i, bn in enumerate(bns): + m, v = bn.running_mean, bn.running_var + sqs[i] += (v + m * m) / num_iter + mus[i] += m / num_iter + # Set the stats and restore momentum values + for i, bn in enumerate(bns): + bn.running_var = sqs[i] - mus[i] * mus[i] + bn.running_mean = mus[i] + bn.momentum = moms[i] + + +def reset_bn_stats(model): + """Resets running BN stats.""" + for m in model.modules(): + if isinstance(m, torch.nn.BatchNorm2d): + m.reset_running_stats() + + +def complexity_conv2d(cx, w_in, w_out, k, stride, padding, groups=1, bias=False): + """Accumulates complexity of Conv2D into cx = (h, w, flops, params, acts).""" + h, w, flops, params, acts = cx["h"], cx["w"], cx["flops"], cx["params"], cx["acts"] + h = (h + 2 * padding - k) // stride + 1 + w = (w + 2 * padding - k) // stride + 1 + flops += k * k * w_in * w_out * h * w // groups + params += k * k * w_in * w_out // groups + flops += w_out if bias else 0 + params += w_out if bias else 0 + acts += w_out * h * w + return {"h": h, "w": w, "flops": flops, "params": params, "acts": acts} + + +def complexity_batchnorm2d(cx, w_in): + """Accumulates complexity of BatchNorm2D into cx = (h, w, flops, params, acts).""" + h, w, flops, params, acts = cx["h"], cx["w"], cx["flops"], cx["params"], cx["acts"] + params += 2 * w_in + return {"h": h, "w": w, "flops": flops, "params": params, "acts": acts} + + +def complexity_maxpool2d(cx, k, stride, padding): + """Accumulates complexity of MaxPool2d into cx = (h, w, flops, params, acts).""" + h, w, flops, params, acts = cx["h"], cx["w"], cx["flops"], cx["params"], cx["acts"] + h = (h + 2 * padding - k) // stride + 1 + w = (w + 2 * padding - k) // stride + 1 + return {"h": h, "w": w, "flops": flops, "params": params, "acts": acts} + + +def complexity(model): + """Compute model complexity (model can be model instance or model class).""" + size = cfg.TRAIN.IM_SIZE + cx = {"h": size, "w": size, "flops": 0, "params": 0, "acts": 0} + cx = model.complexity(cx) + return {"flops": cx["flops"], "params": cx["params"], "acts": cx["acts"]} + + +def drop_connect(x, drop_ratio): + """Drop connect (adapted from DARTS).""" + keep_ratio = 1.0 - drop_ratio + mask = torch.empty([x.shape[0], 1, 1, 1], dtype=x.dtype, device=x.device) + mask.bernoulli_(keep_ratio) + x.div_(keep_ratio) + x.mul_(mask) + return x + + +def get_flat_weights(model): + """Gets all model weights as a single flat vector.""" + return torch.cat([p.data.view(-1, 1) for p in model.parameters()], 0) + + +def set_flat_weights(model, flat_weights): + """Sets all model weights from a single flat vector.""" + k = 0 + for p in model.parameters(): + n = p.data.numel() + p.data.copy_(flat_weights[k : (k + n)].view_as(p.data)) + k += n + assert k == flat_weights.numel() diff --git a/pycls/core/optimizer.py b/pycls/core/optimizer.py new file mode 100644 index 0000000..766a984 --- /dev/null +++ b/pycls/core/optimizer.py @@ -0,0 +1,95 @@ +#!/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. + +"""Optimizer.""" + +import numpy as np +import torch +from pycls.core.config import cfg + + +def construct_optimizer(model): + """Constructs the optimizer. + + Note that the momentum update in PyTorch differs from the one in Caffe2. + In particular, + + Caffe2: + V := mu * V + lr * g + p := p - V + + PyTorch: + V := mu * V + g + p := p - lr * V + + where V is the velocity, mu is the momentum factor, lr is the learning rate, + g is the gradient and p are the parameters. + + Since V is defined independently of the learning rate in PyTorch, + when the learning rate is changed there is no need to perform the + momentum correction by scaling V (unlike in the Caffe2 case). + """ + if cfg.BN.USE_CUSTOM_WEIGHT_DECAY: + # Apply different weight decay to Batchnorm and non-batchnorm parameters. + p_bn = [p for n, p in model.named_parameters() if "bn" in n] + p_non_bn = [p for n, p in model.named_parameters() if "bn" not in n] + optim_params = [ + {"params": p_bn, "weight_decay": cfg.BN.CUSTOM_WEIGHT_DECAY}, + {"params": p_non_bn, "weight_decay": cfg.OPTIM.WEIGHT_DECAY}, + ] + else: + optim_params = model.parameters() + return torch.optim.SGD( + optim_params, + lr=cfg.OPTIM.BASE_LR, + momentum=cfg.OPTIM.MOMENTUM, + weight_decay=cfg.OPTIM.WEIGHT_DECAY, + dampening=cfg.OPTIM.DAMPENING, + nesterov=cfg.OPTIM.NESTEROV, + ) + + +def lr_fun_steps(cur_epoch): + """Steps schedule (cfg.OPTIM.LR_POLICY = 'steps').""" + ind = [i for i, s in enumerate(cfg.OPTIM.STEPS) if cur_epoch >= s][-1] + return cfg.OPTIM.BASE_LR * (cfg.OPTIM.LR_MULT ** ind) + + +def lr_fun_exp(cur_epoch): + """Exponential schedule (cfg.OPTIM.LR_POLICY = 'exp').""" + return cfg.OPTIM.BASE_LR * (cfg.OPTIM.GAMMA ** cur_epoch) + + +def lr_fun_cos(cur_epoch): + """Cosine schedule (cfg.OPTIM.LR_POLICY = 'cos').""" + base_lr, max_epoch = cfg.OPTIM.BASE_LR, cfg.OPTIM.MAX_EPOCH + return 0.5 * base_lr * (1.0 + np.cos(np.pi * cur_epoch / max_epoch)) + + +def get_lr_fun(): + """Retrieves the specified lr policy function""" + lr_fun = "lr_fun_" + cfg.OPTIM.LR_POLICY + if lr_fun not in globals(): + raise NotImplementedError("Unknown LR policy:" + cfg.OPTIM.LR_POLICY) + return globals()[lr_fun] + + +def get_epoch_lr(cur_epoch): + """Retrieves the lr for the given epoch according to the policy.""" + lr = get_lr_fun()(cur_epoch) + # Linear warmup + if cur_epoch < cfg.OPTIM.WARMUP_EPOCHS: + alpha = cur_epoch / cfg.OPTIM.WARMUP_EPOCHS + warmup_factor = cfg.OPTIM.WARMUP_FACTOR * (1.0 - alpha) + alpha + lr *= warmup_factor + return lr + + +def set_lr(optimizer, new_lr): + """Sets the optimizer lr to the specified value.""" + for param_group in optimizer.param_groups: + param_group["lr"] = new_lr diff --git a/pycls/core/plotting.py b/pycls/core/plotting.py new file mode 100644 index 0000000..c310df7 --- /dev/null +++ b/pycls/core/plotting.py @@ -0,0 +1,132 @@ +#!/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. + +"""Plotting functions.""" + +import colorlover as cl +import matplotlib.pyplot as plt +import plotly.graph_objs as go +import plotly.offline as offline +import pycls.core.logging as logging + + +def get_plot_colors(max_colors, color_format="pyplot"): + """Generate colors for plotting.""" + colors = cl.scales["11"]["qual"]["Paired"] + if max_colors > len(colors): + colors = cl.to_rgb(cl.interp(colors, max_colors)) + if color_format == "pyplot": + return [[j / 255.0 for j in c] for c in cl.to_numeric(colors)] + return colors + + +def prepare_plot_data(log_files, names, metric="top1_err"): + """Load logs and extract data for plotting error curves.""" + plot_data = [] + for file, name in zip(log_files, names): + d, data = {}, logging.sort_log_data(logging.load_log_data(file)) + for phase in ["train", "test"]: + x = data[phase + "_epoch"]["epoch_ind"] + y = data[phase + "_epoch"][metric] + d["x_" + phase], d["y_" + phase] = x, y + d[phase + "_label"] = "[{:5.2f}] ".format(min(y) if y else 0) + name + plot_data.append(d) + assert len(plot_data) > 0, "No data to plot" + return plot_data + + +def plot_error_curves_plotly(log_files, names, filename, metric="top1_err"): + """Plot error curves using plotly and save to file.""" + plot_data = prepare_plot_data(log_files, names, metric) + colors = get_plot_colors(len(plot_data), "plotly") + # Prepare data for plots (3 sets, train duplicated w and w/o legend) + data = [] + for i, d in enumerate(plot_data): + s = str(i) + line_train = {"color": colors[i], "dash": "dashdot", "width": 1.5} + line_test = {"color": colors[i], "dash": "solid", "width": 1.5} + data.append( + go.Scatter( + x=d["x_train"], + y=d["y_train"], + mode="lines", + name=d["train_label"], + line=line_train, + legendgroup=s, + visible=True, + showlegend=False, + ) + ) + data.append( + go.Scatter( + x=d["x_test"], + y=d["y_test"], + mode="lines", + name=d["test_label"], + line=line_test, + legendgroup=s, + visible=True, + showlegend=True, + ) + ) + data.append( + go.Scatter( + x=d["x_train"], + y=d["y_train"], + mode="lines", + name=d["train_label"], + line=line_train, + legendgroup=s, + visible=False, + showlegend=True, + ) + ) + # Prepare layout w ability to toggle 'all', 'train', 'test' + titlefont = {"size": 18, "color": "#7f7f7f"} + vis = [[True, True, False], [False, False, True], [False, True, False]] + buttons = zip(["all", "train", "test"], [[{"visible": v}] for v in vis]) + buttons = [{"label": b, "args": v, "method": "update"} for b, v in buttons] + layout = go.Layout( + title=metric + " vs. epoch
[dash=train, solid=test]", + xaxis={"title": "epoch", "titlefont": titlefont}, + yaxis={"title": metric, "titlefont": titlefont}, + showlegend=True, + hoverlabel={"namelength": -1}, + updatemenus=[ + { + "buttons": buttons, + "direction": "down", + "showactive": True, + "x": 1.02, + "xanchor": "left", + "y": 1.08, + "yanchor": "top", + } + ], + ) + # Create plotly plot + offline.plot({"data": data, "layout": layout}, filename=filename) + + +def plot_error_curves_pyplot(log_files, names, filename=None, metric="top1_err"): + """Plot error curves using matplotlib.pyplot and save to file.""" + plot_data = prepare_plot_data(log_files, names, metric) + colors = get_plot_colors(len(names)) + for ind, d in enumerate(plot_data): + c, lbl = colors[ind], d["test_label"] + plt.plot(d["x_train"], d["y_train"], "--", c=c, alpha=0.8) + plt.plot(d["x_test"], d["y_test"], "-", c=c, alpha=0.8, label=lbl) + plt.title(metric + " vs. epoch\n[dash=train, solid=test]", fontsize=14) + plt.xlabel("epoch", fontsize=14) + plt.ylabel(metric, fontsize=14) + plt.grid(alpha=0.4) + plt.legend() + if filename: + plt.savefig(filename) + plt.clf() + else: + plt.show() diff --git a/pycls/core/timer.py b/pycls/core/timer.py new file mode 100644 index 0000000..0dcf7de --- /dev/null +++ b/pycls/core/timer.py @@ -0,0 +1,39 @@ +#!/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. + +"""Timer.""" + +import time + + +class Timer(object): + """A simple timer (adapted from Detectron).""" + + def __init__(self): + self.total_time = None + self.calls = None + self.start_time = None + self.diff = None + self.average_time = None + self.reset() + + def tic(self): + # using time.time as time.clock does not normalize for multithreading + self.start_time = time.time() + + def toc(self): + self.diff = time.time() - self.start_time + self.total_time += self.diff + self.calls += 1 + self.average_time = self.total_time / self.calls + + def reset(self): + self.total_time = 0.0 + self.calls = 0 + self.start_time = 0.0 + self.diff = 0.0 + self.average_time = 0.0 diff --git a/pycls/core/trainer.py b/pycls/core/trainer.py new file mode 100644 index 0000000..fae27f4 --- /dev/null +++ b/pycls/core/trainer.py @@ -0,0 +1,419 @@ +#!/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. + +"""Tools for training and testing a model.""" + +import os +from thop import profile + +import numpy as np +import pycls.core.benchmark as benchmark +import pycls.core.builders as builders +import pycls.core.checkpoint as checkpoint +import pycls.core.config as config +import pycls.core.distributed as dist +import pycls.core.logging as logging +import pycls.core.meters as meters +import pycls.core.net as net +import pycls.core.optimizer as optim +import pycls.datasets.loader as loader +import torch +import torch.nn.functional as F +from pycls.core.config import cfg + + +logger = logging.get_logger(__name__) + + +def setup_env(): + """Sets up environment for training or testing.""" + if dist.is_master_proc(): + # Ensure that the output dir exists + os.makedirs(cfg.OUT_DIR, exist_ok=True) + # Save the config + config.dump_cfg() + # Setup logging + logging.setup_logging() + # Log the config as both human readable and as a json + logger.info("Config:\n{}".format(cfg)) + logger.info(logging.dump_log_data(cfg, "cfg")) + # Fix the RNG seeds (see RNG comment in core/config.py for discussion) + np.random.seed(cfg.RNG_SEED) + torch.manual_seed(cfg.RNG_SEED) + # Configure the CUDNN backend + torch.backends.cudnn.benchmark = cfg.CUDNN.BENCHMARK + + +def setup_model(): + """Sets up a model for training or testing and log the results.""" + # Build the model + model = builders.build_model() + logger.info("Model:\n{}".format(model)) + # Log model complexity + # logger.info(logging.dump_log_data(net.complexity(model), "complexity")) + if cfg.TASK == "seg" and cfg.TRAIN.DATASET == "cityscapes": + h, w = 1025, 2049 + else: + h, w = cfg.TRAIN.IM_SIZE, cfg.TRAIN.IM_SIZE + if cfg.TASK == "jig": + x = torch.randn(1, cfg.JIGSAW_GRID ** 2, cfg.MODEL.INPUT_CHANNELS, h, w) + else: + x = torch.randn(1, cfg.MODEL.INPUT_CHANNELS, h, w) + macs, params = profile(model, inputs=(x, ), verbose=False) + logger.info("Params: {:,}".format(params)) + logger.info("Flops: {:,}".format(macs)) + # Transfer the model to the current GPU device + err_str = "Cannot use more GPU devices than available" + assert cfg.NUM_GPUS <= torch.cuda.device_count(), err_str + cur_device = torch.cuda.current_device() + model = model.cuda(device=cur_device) + # Use multi-process data parallel model in the multi-gpu setting + if cfg.NUM_GPUS > 1: + # Make model replica operate on the current device + model = torch.nn.parallel.DistributedDataParallel( + module=model, device_ids=[cur_device], output_device=cur_device + ) + # Set complexity function to be module's complexity function + # model.complexity = model.module.complexity + return model + + +def train_epoch(train_loader, model, loss_fun, optimizer, train_meter, cur_epoch): + """Performs one epoch of training.""" + # Update drop path prob for NAS + if cfg.MODEL.TYPE == "nas": + m = model.module if cfg.NUM_GPUS > 1 else model + m.set_drop_path_prob(cfg.NAS.DROP_PROB * cur_epoch / cfg.OPTIM.MAX_EPOCH) + # Shuffle the data + loader.shuffle(train_loader, cur_epoch) + # Update the learning rate per epoch + if not cfg.OPTIM.ITER_LR: + lr = optim.get_epoch_lr(cur_epoch) + optim.set_lr(optimizer, lr) + # Enable training mode + model.train() + train_meter.iter_tic() + for cur_iter, (inputs, labels) in enumerate(train_loader): + # Update the learning rate per iter + if cfg.OPTIM.ITER_LR: + lr = optim.get_epoch_lr(cur_epoch + cur_iter / len(train_loader)) + optim.set_lr(optimizer, lr) + # Transfer the data to the current GPU device + inputs, labels = inputs.cuda(), labels.cuda(non_blocking=True) + # Perform the forward pass + preds = model(inputs) + # Compute the loss + if isinstance(preds, tuple): + loss = loss_fun(preds[0], labels) + cfg.NAS.AUX_WEIGHT * loss_fun(preds[1], labels) + preds = preds[0] + else: + loss = loss_fun(preds, labels) + # Perform the backward pass + optimizer.zero_grad() + loss.backward() + # Update the parameters + optimizer.step() + # Compute the errors + if cfg.TASK == "col": + preds = preds.permute(0, 2, 3, 1) + preds = preds.reshape(-1, preds.size(3)) + labels = labels.reshape(-1) + mb_size = inputs.size(0) * inputs.size(2) * inputs.size(3) * cfg.NUM_GPUS + else: + mb_size = inputs.size(0) * cfg.NUM_GPUS + if cfg.TASK == "seg": + # top1_err is in fact inter; top5_err is in fact union + top1_err, top5_err = meters.inter_union(preds, labels, cfg.MODEL.NUM_CLASSES) + else: + ks = [1, min(5, cfg.MODEL.NUM_CLASSES)] # rot only has 4 classes + top1_err, top5_err = meters.topk_errors(preds, labels, ks) + # Combine the stats across the GPUs (no reduction if 1 GPU used) + loss, top1_err, top5_err = dist.scaled_all_reduce([loss, top1_err, top5_err]) + # Copy the stats from GPU to CPU (sync point) + loss = loss.item() + if cfg.TASK == "seg": + top1_err, top5_err = top1_err.cpu().numpy(), top5_err.cpu().numpy() + else: + top1_err, top5_err = top1_err.item(), top5_err.item() + train_meter.iter_toc() + # Update and log stats + train_meter.update_stats(top1_err, top5_err, loss, lr, mb_size) + train_meter.log_iter_stats(cur_epoch, cur_iter) + train_meter.iter_tic() + # Log epoch stats + train_meter.log_epoch_stats(cur_epoch) + train_meter.reset() + + +def search_epoch(train_loader, model, loss_fun, optimizer, train_meter, cur_epoch): + """Performs one epoch of differentiable architecture search.""" + m = model.module if cfg.NUM_GPUS > 1 else model + # Shuffle the data + loader.shuffle(train_loader[0], cur_epoch) + loader.shuffle(train_loader[1], cur_epoch) + # Update the learning rate per epoch + if not cfg.OPTIM.ITER_LR: + lr = optim.get_epoch_lr(cur_epoch) + optim.set_lr(optimizer[0], lr) + # Enable training mode + model.train() + train_meter.iter_tic() + trainB_iter = iter(train_loader[1]) + for cur_iter, (inputs, labels) in enumerate(train_loader[0]): + # Update the learning rate per iter + if cfg.OPTIM.ITER_LR: + lr = optim.get_epoch_lr(cur_epoch + cur_iter / len(train_loader[0])) + optim.set_lr(optimizer[0], lr) + # Transfer the data to the current GPU device + inputs, labels = inputs.cuda(), labels.cuda(non_blocking=True) + # Update architecture + if cur_epoch + cur_iter / len(train_loader[0]) >= cfg.OPTIM.ARCH_EPOCH: + try: + inputsB, labelsB = next(trainB_iter) + except StopIteration: + trainB_iter = iter(train_loader[1]) + inputsB, labelsB = next(trainB_iter) + inputsB, labelsB = inputsB.cuda(), labelsB.cuda(non_blocking=True) + optimizer[1].zero_grad() + loss = m._loss(inputsB, labelsB) + loss.backward() + optimizer[1].step() + # Perform the forward pass + preds = model(inputs) + # Compute the loss + loss = loss_fun(preds, labels) + # Perform the backward pass + optimizer[0].zero_grad() + loss.backward() + torch.nn.utils.clip_grad_norm(model.parameters(), 5.0) + # Update the parameters + optimizer[0].step() + # Compute the errors + if cfg.TASK == "col": + preds = preds.permute(0, 2, 3, 1) + preds = preds.reshape(-1, preds.size(3)) + labels = labels.reshape(-1) + mb_size = inputs.size(0) * inputs.size(2) * inputs.size(3) * cfg.NUM_GPUS + else: + mb_size = inputs.size(0) * cfg.NUM_GPUS + if cfg.TASK == "seg": + # top1_err is in fact inter; top5_err is in fact union + top1_err, top5_err = meters.inter_union(preds, labels, cfg.MODEL.NUM_CLASSES) + else: + ks = [1, min(5, cfg.MODEL.NUM_CLASSES)] # rot only has 4 classes + top1_err, top5_err = meters.topk_errors(preds, labels, ks) + # Combine the stats across the GPUs (no reduction if 1 GPU used) + loss, top1_err, top5_err = dist.scaled_all_reduce([loss, top1_err, top5_err]) + # Copy the stats from GPU to CPU (sync point) + loss = loss.item() + if cfg.TASK == "seg": + top1_err, top5_err = top1_err.cpu().numpy(), top5_err.cpu().numpy() + else: + top1_err, top5_err = top1_err.item(), top5_err.item() + train_meter.iter_toc() + # Update and log stats + train_meter.update_stats(top1_err, top5_err, loss, lr, mb_size) + train_meter.log_iter_stats(cur_epoch, cur_iter) + train_meter.iter_tic() + # Log epoch stats + train_meter.log_epoch_stats(cur_epoch) + train_meter.reset() + # Log genotype + genotype = m.genotype() + logger.info("genotype = %s", genotype) + logger.info(F.softmax(m.net_.alphas_normal, dim=-1)) + logger.info(F.softmax(m.net_.alphas_reduce, dim=-1)) + + +@torch.no_grad() +def test_epoch(test_loader, model, test_meter, cur_epoch): + """Evaluates the model on the test set.""" + # Enable eval mode + model.eval() + test_meter.iter_tic() + for cur_iter, (inputs, labels) in enumerate(test_loader): + # Transfer the data to the current GPU device + inputs, labels = inputs.cuda(), labels.cuda(non_blocking=True) + # Compute the predictions + preds = model(inputs) + # Compute the errors + if cfg.TASK == "col": + preds = preds.permute(0, 2, 3, 1) + preds = preds.reshape(-1, preds.size(3)) + labels = labels.reshape(-1) + mb_size = inputs.size(0) * inputs.size(2) * inputs.size(3) * cfg.NUM_GPUS + else: + mb_size = inputs.size(0) * cfg.NUM_GPUS + if cfg.TASK == "seg": + # top1_err is in fact inter; top5_err is in fact union + top1_err, top5_err = meters.inter_union(preds, labels, cfg.MODEL.NUM_CLASSES) + else: + ks = [1, min(5, cfg.MODEL.NUM_CLASSES)] # rot only has 4 classes + top1_err, top5_err = meters.topk_errors(preds, labels, ks) + # Combine the errors across the GPUs (no reduction if 1 GPU used) + top1_err, top5_err = dist.scaled_all_reduce([top1_err, top5_err]) + # Copy the errors from GPU to CPU (sync point) + if cfg.TASK == "seg": + top1_err, top5_err = top1_err.cpu().numpy(), top5_err.cpu().numpy() + else: + top1_err, top5_err = top1_err.item(), top5_err.item() + test_meter.iter_toc() + # Update and log stats + test_meter.update_stats(top1_err, top5_err, mb_size) + test_meter.log_iter_stats(cur_epoch, cur_iter) + test_meter.iter_tic() + # Log epoch stats + test_meter.log_epoch_stats(cur_epoch) + test_meter.reset() + + +def train_model(): + """Trains the model.""" + # Setup training/testing environment + setup_env() + # Construct the model, loss_fun, and optimizer + model = setup_model() + loss_fun = builders.build_loss_fun().cuda() + if "search" in cfg.MODEL.TYPE: + params_w = [v for k, v in model.named_parameters() if "alphas" not in k] + params_a = [v for k, v in model.named_parameters() if "alphas" in k] + optimizer_w = torch.optim.SGD( + params=params_w, + lr=cfg.OPTIM.BASE_LR, + momentum=cfg.OPTIM.MOMENTUM, + weight_decay=cfg.OPTIM.WEIGHT_DECAY, + dampening=cfg.OPTIM.DAMPENING, + nesterov=cfg.OPTIM.NESTEROV + ) + if cfg.OPTIM.ARCH_OPTIM == "adam": + optimizer_a = torch.optim.Adam( + params=params_a, + lr=cfg.OPTIM.ARCH_BASE_LR, + betas=(0.5, 0.999), + weight_decay=cfg.OPTIM.ARCH_WEIGHT_DECAY + ) + elif cfg.OPTIM.ARCH_OPTIM == "sgd": + optimizer_a = torch.optim.SGD( + params=params_a, + lr=cfg.OPTIM.ARCH_BASE_LR, + momentum=cfg.OPTIM.MOMENTUM, + weight_decay=cfg.OPTIM.ARCH_WEIGHT_DECAY, + dampening=cfg.OPTIM.DAMPENING, + nesterov=cfg.OPTIM.NESTEROV + ) + optimizer = [optimizer_w, optimizer_a] + else: + optimizer = optim.construct_optimizer(model) + # Load checkpoint or initial weights + start_epoch = 0 + if cfg.TRAIN.AUTO_RESUME and checkpoint.has_checkpoint(): + last_checkpoint = checkpoint.get_last_checkpoint() + checkpoint_epoch = checkpoint.load_checkpoint(last_checkpoint, model, optimizer) + logger.info("Loaded checkpoint from: {}".format(last_checkpoint)) + start_epoch = checkpoint_epoch + 1 + elif cfg.TRAIN.WEIGHTS: + checkpoint.load_checkpoint(cfg.TRAIN.WEIGHTS, model) + logger.info("Loaded initial weights from: {}".format(cfg.TRAIN.WEIGHTS)) + # Create data loaders and meters + if cfg.TRAIN.PORTION < 1: + if "search" in cfg.MODEL.TYPE: + train_loader = [loader._construct_loader( + dataset_name=cfg.TRAIN.DATASET, + split=cfg.TRAIN.SPLIT, + batch_size=int(cfg.TRAIN.BATCH_SIZE / cfg.NUM_GPUS), + shuffle=True, + drop_last=True, + portion=cfg.TRAIN.PORTION, + side="l" + ), + loader._construct_loader( + dataset_name=cfg.TRAIN.DATASET, + split=cfg.TRAIN.SPLIT, + batch_size=int(cfg.TRAIN.BATCH_SIZE / cfg.NUM_GPUS), + shuffle=True, + drop_last=True, + portion=cfg.TRAIN.PORTION, + side="r" + )] + else: + train_loader = loader._construct_loader( + dataset_name=cfg.TRAIN.DATASET, + split=cfg.TRAIN.SPLIT, + batch_size=int(cfg.TRAIN.BATCH_SIZE / cfg.NUM_GPUS), + shuffle=True, + drop_last=True, + portion=cfg.TRAIN.PORTION, + side="l" + ) + test_loader = loader._construct_loader( + dataset_name=cfg.TRAIN.DATASET, + split=cfg.TRAIN.SPLIT, + batch_size=int(cfg.TRAIN.BATCH_SIZE / cfg.NUM_GPUS), + shuffle=False, + drop_last=False, + portion=cfg.TRAIN.PORTION, + side="r" + ) + else: + train_loader = loader.construct_train_loader() + test_loader = loader.construct_test_loader() + train_meter_type = meters.TrainMeterIoU if cfg.TASK == "seg" else meters.TrainMeter + test_meter_type = meters.TestMeterIoU if cfg.TASK == "seg" else meters.TestMeter + l = train_loader[0] if isinstance(train_loader, list) else train_loader + train_meter = train_meter_type(len(l)) + test_meter = test_meter_type(len(test_loader)) + # Compute model and loader timings + if start_epoch == 0 and cfg.PREC_TIME.NUM_ITER > 0: + l = train_loader[0] if isinstance(train_loader, list) else train_loader + benchmark.compute_time_full(model, loss_fun, l, test_loader) + # Perform the training loop + logger.info("Start epoch: {}".format(start_epoch + 1)) + for cur_epoch in range(start_epoch, cfg.OPTIM.MAX_EPOCH): + # Train for one epoch + f = search_epoch if "search" in cfg.MODEL.TYPE else train_epoch + f(train_loader, model, loss_fun, optimizer, train_meter, cur_epoch) + # Compute precise BN stats + if cfg.BN.USE_PRECISE_STATS: + net.compute_precise_bn_stats(model, train_loader) + # Save a checkpoint + if (cur_epoch + 1) % cfg.TRAIN.CHECKPOINT_PERIOD == 0: + checkpoint_file = checkpoint.save_checkpoint(model, optimizer, cur_epoch) + logger.info("Wrote checkpoint to: {}".format(checkpoint_file)) + # Evaluate the model + next_epoch = cur_epoch + 1 + if next_epoch % cfg.TRAIN.EVAL_PERIOD == 0 or next_epoch == cfg.OPTIM.MAX_EPOCH: + test_epoch(test_loader, model, test_meter, cur_epoch) + + +def test_model(): + """Evaluates a trained model.""" + # Setup training/testing environment + setup_env() + # Construct the model + model = setup_model() + # Load model weights + checkpoint.load_checkpoint(cfg.TEST.WEIGHTS, model) + logger.info("Loaded model weights from: {}".format(cfg.TEST.WEIGHTS)) + # Create data loaders and meters + test_loader = loader.construct_test_loader() + test_meter = meters.TestMeter(len(test_loader)) + # Evaluate the model + test_epoch(test_loader, model, test_meter, 0) + + +def time_model(): + """Times model and data loader.""" + # Setup training/testing environment + setup_env() + # Construct the model and loss_fun + model = setup_model() + loss_fun = builders.build_loss_fun().cuda() + # Create data loaders + train_loader = loader.construct_train_loader() + test_loader = loader.construct_test_loader() + # Compute model and loader timings + benchmark.compute_time_full(model, loss_fun, train_loader, test_loader) diff --git a/pycls/models/__init__.py b/pycls/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pycls/models/anynet.py b/pycls/models/anynet.py new file mode 100644 index 0000000..32a620c --- /dev/null +++ b/pycls/models/anynet.py @@ -0,0 +1,406 @@ +#!/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. + +"""AnyNet models.""" + +import pycls.core.net as net +import torch.nn as nn +from pycls.core.config import cfg + + +def get_stem_fun(stem_type): + """Retrieves the stem function by name.""" + stem_funs = { + "res_stem_cifar": ResStemCifar, + "res_stem_in": ResStemIN, + "simple_stem_in": SimpleStemIN, + } + err_str = "Stem type '{}' not supported" + assert stem_type in stem_funs.keys(), err_str.format(stem_type) + return stem_funs[stem_type] + + +def get_block_fun(block_type): + """Retrieves the block function by name.""" + block_funs = { + "vanilla_block": VanillaBlock, + "res_basic_block": ResBasicBlock, + "res_bottleneck_block": ResBottleneckBlock, + } + err_str = "Block type '{}' not supported" + assert block_type in block_funs.keys(), err_str.format(block_type) + return block_funs[block_type] + + +class AnyHead(nn.Module): + """AnyNet head: AvgPool, 1x1.""" + + def __init__(self, w_in, nc): + super(AnyHead, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) + self.fc = nn.Linear(w_in, nc, bias=True) + + def forward(self, x): + x = self.avg_pool(x) + x = x.view(x.size(0), -1) + x = self.fc(x) + return x + + @staticmethod + def complexity(cx, w_in, nc): + cx["h"], cx["w"] = 1, 1 + cx = net.complexity_conv2d(cx, w_in, nc, 1, 1, 0, bias=True) + return cx + + +class VanillaBlock(nn.Module): + """Vanilla block: [3x3 conv, BN, Relu] x2.""" + + def __init__(self, w_in, w_out, stride, bm=None, gw=None, se_r=None): + err_str = "Vanilla block does not support bm, gw, and se_r options" + assert bm is None and gw is None and se_r is None, err_str + super(VanillaBlock, self).__init__() + self.a = nn.Conv2d(w_in, w_out, 3, stride=stride, padding=1, bias=False) + self.a_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.a_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + self.b = nn.Conv2d(w_out, w_out, 3, stride=1, padding=1, bias=False) + self.b_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.b_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, bm=None, gw=None, se_r=None): + err_str = "Vanilla block does not support bm, gw, and se_r options" + assert bm is None and gw is None and se_r is None, err_str + cx = net.complexity_conv2d(cx, w_in, w_out, 3, stride, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + cx = net.complexity_conv2d(cx, w_out, w_out, 3, 1, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class BasicTransform(nn.Module): + """Basic transformation: [3x3 conv, BN, Relu] x2.""" + + def __init__(self, w_in, w_out, stride): + super(BasicTransform, self).__init__() + self.a = nn.Conv2d(w_in, w_out, 3, stride=stride, padding=1, bias=False) + self.a_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.a_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + self.b = nn.Conv2d(w_out, w_out, 3, stride=1, padding=1, bias=False) + self.b_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.b_bn.final_bn = True + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride): + cx = net.complexity_conv2d(cx, w_in, w_out, 3, stride, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + cx = net.complexity_conv2d(cx, w_out, w_out, 3, 1, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class ResBasicBlock(nn.Module): + """Residual basic block: x + F(x), F = basic transform.""" + + def __init__(self, w_in, w_out, stride, bm=None, gw=None, se_r=None): + err_str = "Basic transform does not support bm, gw, and se_r options" + assert bm is None and gw is None and se_r is None, err_str + super(ResBasicBlock, self).__init__() + self.proj_block = (w_in != w_out) or (stride != 1) + if self.proj_block: + self.proj = nn.Conv2d(w_in, w_out, 1, stride=stride, padding=0, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.f = BasicTransform(w_in, w_out, stride) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + + def forward(self, x): + if self.proj_block: + x = self.bn(self.proj(x)) + self.f(x) + else: + x = x + self.f(x) + x = self.relu(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, bm=None, gw=None, se_r=None): + err_str = "Basic transform does not support bm, gw, and se_r options" + assert bm is None and gw is None and se_r is None, err_str + proj_block = (w_in != w_out) or (stride != 1) + if proj_block: + h, w = cx["h"], cx["w"] + cx = net.complexity_conv2d(cx, w_in, w_out, 1, stride, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + cx["h"], cx["w"] = h, w # parallel branch + cx = BasicTransform.complexity(cx, w_in, w_out, stride) + return cx + + +class SE(nn.Module): + """Squeeze-and-Excitation (SE) block: AvgPool, FC, ReLU, FC, Sigmoid.""" + + def __init__(self, w_in, w_se): + super(SE, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) + self.f_ex = nn.Sequential( + nn.Conv2d(w_in, w_se, 1, bias=True), + nn.ReLU(inplace=cfg.MEM.RELU_INPLACE), + nn.Conv2d(w_se, w_in, 1, bias=True), + nn.Sigmoid(), + ) + + def forward(self, x): + return x * self.f_ex(self.avg_pool(x)) + + @staticmethod + def complexity(cx, w_in, w_se): + h, w = cx["h"], cx["w"] + cx["h"], cx["w"] = 1, 1 + cx = net.complexity_conv2d(cx, w_in, w_se, 1, 1, 0, bias=True) + cx = net.complexity_conv2d(cx, w_se, w_in, 1, 1, 0, bias=True) + cx["h"], cx["w"] = h, w + return cx + + +class BottleneckTransform(nn.Module): + """Bottleneck transformation: 1x1, 3x3 [+SE], 1x1.""" + + def __init__(self, w_in, w_out, stride, bm, gw, se_r): + super(BottleneckTransform, self).__init__() + w_b = int(round(w_out * bm)) + g = w_b // gw + self.a = nn.Conv2d(w_in, w_b, 1, stride=1, padding=0, bias=False) + self.a_bn = nn.BatchNorm2d(w_b, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.a_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + self.b = nn.Conv2d(w_b, w_b, 3, stride=stride, padding=1, groups=g, bias=False) + self.b_bn = nn.BatchNorm2d(w_b, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.b_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + if se_r: + w_se = int(round(w_in * se_r)) + self.se = SE(w_b, w_se) + self.c = nn.Conv2d(w_b, w_out, 1, stride=1, padding=0, bias=False) + self.c_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.c_bn.final_bn = True + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, bm, gw, se_r): + w_b = int(round(w_out * bm)) + g = w_b // gw + cx = net.complexity_conv2d(cx, w_in, w_b, 1, 1, 0) + cx = net.complexity_batchnorm2d(cx, w_b) + cx = net.complexity_conv2d(cx, w_b, w_b, 3, stride, 1, g) + cx = net.complexity_batchnorm2d(cx, w_b) + if se_r: + w_se = int(round(w_in * se_r)) + cx = SE.complexity(cx, w_b, w_se) + cx = net.complexity_conv2d(cx, w_b, w_out, 1, 1, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class ResBottleneckBlock(nn.Module): + """Residual bottleneck block: x + F(x), F = bottleneck transform.""" + + def __init__(self, w_in, w_out, stride, bm=1.0, gw=1, se_r=None): + super(ResBottleneckBlock, self).__init__() + # Use skip connection with projection if shape changes + self.proj_block = (w_in != w_out) or (stride != 1) + if self.proj_block: + self.proj = nn.Conv2d(w_in, w_out, 1, stride=stride, padding=0, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.f = BottleneckTransform(w_in, w_out, stride, bm, gw, se_r) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + + def forward(self, x): + if self.proj_block: + x = self.bn(self.proj(x)) + self.f(x) + else: + x = x + self.f(x) + x = self.relu(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, bm=1.0, gw=1, se_r=None): + proj_block = (w_in != w_out) or (stride != 1) + if proj_block: + h, w = cx["h"], cx["w"] + cx = net.complexity_conv2d(cx, w_in, w_out, 1, stride, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + cx["h"], cx["w"] = h, w # parallel branch + cx = BottleneckTransform.complexity(cx, w_in, w_out, stride, bm, gw, se_r) + return cx + + +class ResStemCifar(nn.Module): + """ResNet stem for CIFAR: 3x3, BN, ReLU.""" + + def __init__(self, w_in, w_out): + super(ResStemCifar, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 3, stride=1, padding=1, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out): + cx = net.complexity_conv2d(cx, w_in, w_out, 3, 1, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class ResStemIN(nn.Module): + """ResNet stem for ImageNet: 7x7, BN, ReLU, MaxPool.""" + + def __init__(self, w_in, w_out): + super(ResStemIN, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 7, stride=2, padding=3, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + self.pool = nn.MaxPool2d(3, stride=2, padding=1) + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out): + cx = net.complexity_conv2d(cx, w_in, w_out, 7, 2, 3) + cx = net.complexity_batchnorm2d(cx, w_out) + cx = net.complexity_maxpool2d(cx, 3, 2, 1) + return cx + + +class SimpleStemIN(nn.Module): + """Simple stem for ImageNet: 3x3, BN, ReLU.""" + + def __init__(self, w_in, w_out): + super(SimpleStemIN, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 3, stride=2, padding=1, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out): + cx = net.complexity_conv2d(cx, w_in, w_out, 3, 2, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class AnyStage(nn.Module): + """AnyNet stage (sequence of blocks w/ the same output shape).""" + + def __init__(self, w_in, w_out, stride, d, block_fun, bm, gw, se_r): + super(AnyStage, self).__init__() + for i in range(d): + b_stride = stride if i == 0 else 1 + b_w_in = w_in if i == 0 else w_out + name = "b{}".format(i + 1) + self.add_module(name, block_fun(b_w_in, w_out, b_stride, bm, gw, se_r)) + + def forward(self, x): + for block in self.children(): + x = block(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, d, block_fun, bm, gw, se_r): + for i in range(d): + b_stride = stride if i == 0 else 1 + b_w_in = w_in if i == 0 else w_out + cx = block_fun.complexity(cx, b_w_in, w_out, b_stride, bm, gw, se_r) + return cx + + +class AnyNet(nn.Module): + """AnyNet model.""" + + @staticmethod + def get_args(): + return { + "stem_type": cfg.ANYNET.STEM_TYPE, + "stem_w": cfg.ANYNET.STEM_W, + "block_type": cfg.ANYNET.BLOCK_TYPE, + "ds": cfg.ANYNET.DEPTHS, + "ws": cfg.ANYNET.WIDTHS, + "ss": cfg.ANYNET.STRIDES, + "bms": cfg.ANYNET.BOT_MULS, + "gws": cfg.ANYNET.GROUP_WS, + "se_r": cfg.ANYNET.SE_R if cfg.ANYNET.SE_ON else None, + "nc": cfg.MODEL.NUM_CLASSES, + } + + def __init__(self, **kwargs): + super(AnyNet, self).__init__() + kwargs = self.get_args() if not kwargs else kwargs + #print(kwargs) + self._construct(**kwargs) + self.apply(net.init_weights) + + def _construct(self, stem_type, stem_w, block_type, ds, ws, ss, bms, gws, se_r, nc): + # Generate dummy bot muls and gs for models that do not use them + bms = bms if bms else [None for _d in ds] + gws = gws if gws else [None for _d in ds] + stage_params = list(zip(ds, ws, ss, bms, gws)) + stem_fun = get_stem_fun(stem_type) + self.stem = stem_fun(3, stem_w) + block_fun = get_block_fun(block_type) + prev_w = stem_w + for i, (d, w, s, bm, gw) in enumerate(stage_params): + name = "s{}".format(i + 1) + self.add_module(name, AnyStage(prev_w, w, s, d, block_fun, bm, gw, se_r)) + prev_w = w + self.head = AnyHead(w_in=prev_w, nc=nc) + + def forward(self, x, get_ints=False): + for module in self.children(): + x = module(x) + return x + + @staticmethod + def complexity(cx, **kwargs): + """Computes model complexity. If you alter the model, make sure to update.""" + kwargs = AnyNet.get_args() if not kwargs else kwargs + return AnyNet._complexity(cx, **kwargs) + + @staticmethod + def _complexity(cx, stem_type, stem_w, block_type, ds, ws, ss, bms, gws, se_r, nc): + bms = bms if bms else [None for _d in ds] + gws = gws if gws else [None for _d in ds] + stage_params = list(zip(ds, ws, ss, bms, gws)) + stem_fun = get_stem_fun(stem_type) + cx = stem_fun.complexity(cx, 3, stem_w) + block_fun = get_block_fun(block_type) + prev_w = stem_w + for d, w, s, bm, gw in stage_params: + cx = AnyStage.complexity(cx, prev_w, w, s, d, block_fun, bm, gw, se_r) + prev_w = w + cx = AnyHead.complexity(cx, prev_w, nc) + return cx diff --git a/pycls/models/common.py b/pycls/models/common.py new file mode 100644 index 0000000..0f78466 --- /dev/null +++ b/pycls/models/common.py @@ -0,0 +1,108 @@ +#!/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. + +import torch +import torch.nn as nn + +from pycls.core.config import cfg + + +def Preprocess(x): + if cfg.TASK == 'jig': + assert len(x.shape) == 5, 'Wrong tensor dimension for jigsaw' + assert x.shape[1] == cfg.JIGSAW_GRID ** 2, 'Wrong grid for jigsaw' + x = x.view([x.shape[0] * x.shape[1], x.shape[2], x.shape[3], x.shape[4]]) + return x + + +class Classifier(nn.Module): + def __init__(self, channels, num_classes): + super(Classifier, self).__init__() + if cfg.TASK == 'jig': + self.jig_sq = cfg.JIGSAW_GRID ** 2 + self.pooling = nn.AdaptiveAvgPool2d(1) + self.classifier = nn.Linear(channels * self.jig_sq, num_classes) + elif cfg.TASK == 'col': + self.classifier = nn.Conv2d(channels, num_classes, kernel_size=1, stride=1) + elif cfg.TASK == 'seg': + self.classifier = ASPP(channels, cfg.MODEL.ASPP_CHANNELS, num_classes, cfg.MODEL.ASPP_RATES) + else: + self.pooling = nn.AdaptiveAvgPool2d(1) + self.classifier = nn.Linear(channels, num_classes) + + def forward(self, x, shape): + if cfg.TASK == 'jig': + x = self.pooling(x) + x = x.view([x.shape[0] // self.jig_sq, x.shape[1] * self.jig_sq, x.shape[2], x.shape[3]]) + x = self.classifier(x.view(x.size(0), -1)) + elif cfg.TASK in ['col', 'seg']: + x = self.classifier(x) + x = nn.Upsample(shape, mode='bilinear', align_corners=True)(x) + else: + x = self.pooling(x) + x = self.classifier(x.view(x.size(0), -1)) + return x + + +class ASPP(nn.Module): + def __init__(self, in_channels, out_channels, num_classes, rates): + super(ASPP, self).__init__() + assert len(rates) in [1, 3] + self.rates = rates + self.global_pooling = nn.AdaptiveAvgPool2d(1) + self.aspp1 = nn.Sequential( + nn.Conv2d(in_channels, out_channels, 1, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ) + self.aspp2 = nn.Sequential( + nn.Conv2d(in_channels, out_channels, 3, dilation=rates[0], + padding=rates[0], bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ) + if len(self.rates) == 3: + self.aspp3 = nn.Sequential( + nn.Conv2d(in_channels, out_channels, 3, dilation=rates[1], + padding=rates[1], bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ) + self.aspp4 = nn.Sequential( + nn.Conv2d(in_channels, out_channels, 3, dilation=rates[2], + padding=rates[2], bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ) + self.aspp5 = nn.Sequential( + nn.Conv2d(in_channels, out_channels, 1, bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True) + ) + self.classifier = nn.Sequential( + nn.Conv2d(out_channels * (len(rates) + 2), out_channels, 1, + bias=False), + nn.BatchNorm2d(out_channels), + nn.ReLU(inplace=True), + nn.Conv2d(out_channels, num_classes, 1) + ) + + def forward(self, x): + x1 = self.aspp1(x) + x2 = self.aspp2(x) + x5 = self.global_pooling(x) + x5 = self.aspp5(x5) + x5 = nn.Upsample((x.shape[2], x.shape[3]), mode='bilinear', + align_corners=True)(x5) + if len(self.rates) == 3: + x3 = self.aspp3(x) + x4 = self.aspp4(x) + x = torch.cat((x1, x2, x3, x4, x5), 1) + else: + x = torch.cat((x1, x2, x5), 1) + x = self.classifier(x) + return x diff --git a/pycls/models/effnet.py b/pycls/models/effnet.py new file mode 100644 index 0000000..95f2ad1 --- /dev/null +++ b/pycls/models/effnet.py @@ -0,0 +1,232 @@ +#!/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. + +"""EfficientNet models.""" + +import pycls.core.net as net +import torch +import torch.nn as nn +from pycls.core.config import cfg + + +class EffHead(nn.Module): + """EfficientNet head: 1x1, BN, Swish, AvgPool, Dropout, FC.""" + + def __init__(self, w_in, w_out, nc): + super(EffHead, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 1, stride=1, padding=0, bias=False) + self.conv_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.conv_swish = Swish() + self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) + if cfg.EN.DROPOUT_RATIO > 0.0: + self.dropout = nn.Dropout(p=cfg.EN.DROPOUT_RATIO) + self.fc = nn.Linear(w_out, nc, bias=True) + + def forward(self, x): + x = self.conv_swish(self.conv_bn(self.conv(x))) + x = self.avg_pool(x) + x = x.view(x.size(0), -1) + x = self.dropout(x) if hasattr(self, "dropout") else x + x = self.fc(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, nc): + cx = net.complexity_conv2d(cx, w_in, w_out, 1, 1, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + cx["h"], cx["w"] = 1, 1 + cx = net.complexity_conv2d(cx, w_out, nc, 1, 1, 0, bias=True) + return cx + + +class Swish(nn.Module): + """Swish activation function: x * sigmoid(x).""" + + def __init__(self): + super(Swish, self).__init__() + + def forward(self, x): + return x * torch.sigmoid(x) + + +class SE(nn.Module): + """Squeeze-and-Excitation (SE) block w/ Swish: AvgPool, FC, Swish, FC, Sigmoid.""" + + def __init__(self, w_in, w_se): + super(SE, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) + self.f_ex = nn.Sequential( + nn.Conv2d(w_in, w_se, 1, bias=True), + Swish(), + nn.Conv2d(w_se, w_in, 1, bias=True), + nn.Sigmoid(), + ) + + def forward(self, x): + return x * self.f_ex(self.avg_pool(x)) + + @staticmethod + def complexity(cx, w_in, w_se): + h, w = cx["h"], cx["w"] + cx["h"], cx["w"] = 1, 1 + cx = net.complexity_conv2d(cx, w_in, w_se, 1, 1, 0, bias=True) + cx = net.complexity_conv2d(cx, w_se, w_in, 1, 1, 0, bias=True) + cx["h"], cx["w"] = h, w + return cx + + +class MBConv(nn.Module): + """Mobile inverted bottleneck block w/ SE (MBConv).""" + + def __init__(self, w_in, exp_r, kernel, stride, se_r, w_out): + # expansion, 3x3 dwise, BN, Swish, SE, 1x1, BN, skip_connection + super(MBConv, self).__init__() + self.exp = None + w_exp = int(w_in * exp_r) + if w_exp != w_in: + self.exp = nn.Conv2d(w_in, w_exp, 1, stride=1, padding=0, bias=False) + self.exp_bn = nn.BatchNorm2d(w_exp, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.exp_swish = Swish() + dwise_args = {"groups": w_exp, "padding": (kernel - 1) // 2, "bias": False} + self.dwise = nn.Conv2d(w_exp, w_exp, kernel, stride=stride, **dwise_args) + self.dwise_bn = nn.BatchNorm2d(w_exp, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.dwise_swish = Swish() + self.se = SE(w_exp, int(w_in * se_r)) + self.lin_proj = nn.Conv2d(w_exp, w_out, 1, stride=1, padding=0, bias=False) + self.lin_proj_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + # Skip connection if in and out shapes are the same (MN-V2 style) + self.has_skip = stride == 1 and w_in == w_out + + def forward(self, x): + f_x = x + if self.exp: + f_x = self.exp_swish(self.exp_bn(self.exp(f_x))) + f_x = self.dwise_swish(self.dwise_bn(self.dwise(f_x))) + f_x = self.se(f_x) + f_x = self.lin_proj_bn(self.lin_proj(f_x)) + if self.has_skip: + if self.training and cfg.EN.DC_RATIO > 0.0: + f_x = net.drop_connect(f_x, cfg.EN.DC_RATIO) + f_x = x + f_x + return f_x + + @staticmethod + def complexity(cx, w_in, exp_r, kernel, stride, se_r, w_out): + w_exp = int(w_in * exp_r) + if w_exp != w_in: + cx = net.complexity_conv2d(cx, w_in, w_exp, 1, 1, 0) + cx = net.complexity_batchnorm2d(cx, w_exp) + padding = (kernel - 1) // 2 + cx = net.complexity_conv2d(cx, w_exp, w_exp, kernel, stride, padding, w_exp) + cx = net.complexity_batchnorm2d(cx, w_exp) + cx = SE.complexity(cx, w_exp, int(w_in * se_r)) + cx = net.complexity_conv2d(cx, w_exp, w_out, 1, 1, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class EffStage(nn.Module): + """EfficientNet stage.""" + + def __init__(self, w_in, exp_r, kernel, stride, se_r, w_out, d): + super(EffStage, self).__init__() + for i in range(d): + b_stride = stride if i == 0 else 1 + b_w_in = w_in if i == 0 else w_out + name = "b{}".format(i + 1) + self.add_module(name, MBConv(b_w_in, exp_r, kernel, b_stride, se_r, w_out)) + + def forward(self, x): + for block in self.children(): + x = block(x) + return x + + @staticmethod + def complexity(cx, w_in, exp_r, kernel, stride, se_r, w_out, d): + for i in range(d): + b_stride = stride if i == 0 else 1 + b_w_in = w_in if i == 0 else w_out + cx = MBConv.complexity(cx, b_w_in, exp_r, kernel, b_stride, se_r, w_out) + return cx + + +class StemIN(nn.Module): + """EfficientNet stem for ImageNet: 3x3, BN, Swish.""" + + def __init__(self, w_in, w_out): + super(StemIN, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 3, stride=2, padding=1, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.swish = Swish() + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out): + cx = net.complexity_conv2d(cx, w_in, w_out, 3, 2, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class EffNet(nn.Module): + """EfficientNet model.""" + + @staticmethod + def get_args(): + return { + "stem_w": cfg.EN.STEM_W, + "ds": cfg.EN.DEPTHS, + "ws": cfg.EN.WIDTHS, + "exp_rs": cfg.EN.EXP_RATIOS, + "se_r": cfg.EN.SE_R, + "ss": cfg.EN.STRIDES, + "ks": cfg.EN.KERNELS, + "head_w": cfg.EN.HEAD_W, + "nc": cfg.MODEL.NUM_CLASSES, + } + + def __init__(self): + err_str = "Dataset {} is not supported" + assert cfg.TRAIN.DATASET in ["imagenet"], err_str.format(cfg.TRAIN.DATASET) + assert cfg.TEST.DATASET in ["imagenet"], err_str.format(cfg.TEST.DATASET) + super(EffNet, self).__init__() + self._construct(**EffNet.get_args()) + self.apply(net.init_weights) + + def _construct(self, stem_w, ds, ws, exp_rs, se_r, ss, ks, head_w, nc): + stage_params = list(zip(ds, ws, exp_rs, ss, ks)) + self.stem = StemIN(3, stem_w) + prev_w = stem_w + for i, (d, w, exp_r, stride, kernel) in enumerate(stage_params): + name = "s{}".format(i + 1) + self.add_module(name, EffStage(prev_w, exp_r, kernel, stride, se_r, w, d)) + prev_w = w + self.head = EffHead(prev_w, head_w, nc) + + def forward(self, x): + for module in self.children(): + x = module(x) + return x + + @staticmethod + def complexity(cx): + """Computes model complexity. If you alter the model, make sure to update.""" + return EffNet._complexity(cx, **EffNet.get_args()) + + @staticmethod + def _complexity(cx, stem_w, ds, ws, exp_rs, se_r, ss, ks, head_w, nc): + stage_params = list(zip(ds, ws, exp_rs, ss, ks)) + cx = StemIN.complexity(cx, 3, stem_w) + prev_w = stem_w + for d, w, exp_r, stride, kernel in stage_params: + cx = EffStage.complexity(cx, prev_w, exp_r, kernel, stride, se_r, w, d) + prev_w = w + cx = EffHead.complexity(cx, prev_w, head_w, nc) + return cx diff --git a/pycls/models/nas/genotypes.py b/pycls/models/nas/genotypes.py new file mode 100644 index 0000000..fded6e9 --- /dev/null +++ b/pycls/models/nas/genotypes.py @@ -0,0 +1,634 @@ +#!/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. + +"""NAS genotypes (adopted from DARTS).""" + +from collections import namedtuple + + +Genotype = namedtuple('Genotype', 'normal normal_concat reduce reduce_concat') + + +# NASNet ops +NASNET_OPS = [ + 'skip_connect', + 'conv_3x1_1x3', + 'conv_7x1_1x7', + 'dil_conv_3x3', + 'avg_pool_3x3', + 'max_pool_3x3', + 'max_pool_5x5', + 'max_pool_7x7', + 'conv_1x1', + 'conv_3x3', + 'sep_conv_3x3', + 'sep_conv_5x5', + 'sep_conv_7x7', +] + +# ENAS ops +ENAS_OPS = [ + 'skip_connect', + 'sep_conv_3x3', + 'sep_conv_5x5', + 'avg_pool_3x3', + 'max_pool_3x3', +] + +# AmoebaNet ops +AMOEBA_OPS = [ + 'skip_connect', + 'sep_conv_3x3', + 'sep_conv_5x5', + 'sep_conv_7x7', + 'avg_pool_3x3', + 'max_pool_3x3', + 'dil_sep_conv_3x3', + 'conv_7x1_1x7', +] + +# NAO ops +NAO_OPS = [ + 'skip_connect', + 'conv_1x1', + 'conv_3x3', + 'conv_3x1_1x3', + 'conv_7x1_1x7', + 'max_pool_2x2', + 'max_pool_3x3', + 'max_pool_5x5', + 'avg_pool_2x2', + 'avg_pool_3x3', + 'avg_pool_5x5', +] + +# PNAS ops +PNAS_OPS = [ + 'sep_conv_3x3', + 'sep_conv_5x5', + 'sep_conv_7x7', + 'conv_7x1_1x7', + 'skip_connect', + 'avg_pool_3x3', + 'max_pool_3x3', + 'dil_conv_3x3', +] + +# DARTS ops +DARTS_OPS = [ + 'none', + 'max_pool_3x3', + 'avg_pool_3x3', + 'skip_connect', + 'sep_conv_3x3', + 'sep_conv_5x5', + 'dil_conv_3x3', + 'dil_conv_5x5', +] + + +NASNet = Genotype( + normal=[ + ('sep_conv_5x5', 1), + ('sep_conv_3x3', 0), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 0), + ('avg_pool_3x3', 1), + ('skip_connect', 0), + ('avg_pool_3x3', 0), + ('avg_pool_3x3', 0), + ('sep_conv_3x3', 1), + ('skip_connect', 1), + ], + normal_concat=[2, 3, 4, 5, 6], + reduce=[ + ('sep_conv_5x5', 1), + ('sep_conv_7x7', 0), + ('max_pool_3x3', 1), + ('sep_conv_7x7', 0), + ('avg_pool_3x3', 1), + ('sep_conv_5x5', 0), + ('skip_connect', 3), + ('avg_pool_3x3', 2), + ('sep_conv_3x3', 2), + ('max_pool_3x3', 1), + ], + reduce_concat=[4, 5, 6], +) + + +PNASNet = Genotype( + normal=[ + ('sep_conv_5x5', 0), + ('max_pool_3x3', 0), + ('sep_conv_7x7', 1), + ('max_pool_3x3', 1), + ('sep_conv_5x5', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 4), + ('max_pool_3x3', 1), + ('sep_conv_3x3', 0), + ('skip_connect', 1), + ], + normal_concat=[2, 3, 4, 5, 6], + reduce=[ + ('sep_conv_5x5', 0), + ('max_pool_3x3', 0), + ('sep_conv_7x7', 1), + ('max_pool_3x3', 1), + ('sep_conv_5x5', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 4), + ('max_pool_3x3', 1), + ('sep_conv_3x3', 0), + ('skip_connect', 1), + ], + reduce_concat=[2, 3, 4, 5, 6], +) + + +AmoebaNet = Genotype( + normal=[ + ('avg_pool_3x3', 0), + ('max_pool_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_5x5', 2), + ('sep_conv_3x3', 0), + ('avg_pool_3x3', 3), + ('sep_conv_3x3', 1), + ('skip_connect', 1), + ('skip_connect', 0), + ('avg_pool_3x3', 1), + ], + normal_concat=[4, 5, 6], + reduce=[ + ('avg_pool_3x3', 0), + ('sep_conv_3x3', 1), + ('max_pool_3x3', 0), + ('sep_conv_7x7', 2), + ('sep_conv_7x7', 0), + ('avg_pool_3x3', 1), + ('max_pool_3x3', 0), + ('max_pool_3x3', 1), + ('conv_7x1_1x7', 0), + ('sep_conv_3x3', 5), + ], + reduce_concat=[3, 4, 6] +) + + +DARTS_V1 = Genotype( + normal=[ + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('skip_connect', 0), + ('sep_conv_3x3', 1), + ('skip_connect', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('skip_connect', 2) + ], + normal_concat=[2, 3, 4, 5], + reduce=[ + ('max_pool_3x3', 0), + ('max_pool_3x3', 1), + ('skip_connect', 2), + ('max_pool_3x3', 0), + ('max_pool_3x3', 0), + ('skip_connect', 2), + ('skip_connect', 2), + ('avg_pool_3x3', 0) + ], + reduce_concat=[2, 3, 4, 5] +) + + +DARTS_V2 = Genotype( + normal=[ + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 1), + ('skip_connect', 0), + ('skip_connect', 0), + ('dil_conv_3x3', 2) + ], + normal_concat=[2, 3, 4, 5], + reduce=[ + ('max_pool_3x3', 0), + ('max_pool_3x3', 1), + ('skip_connect', 2), + ('max_pool_3x3', 1), + ('max_pool_3x3', 0), + ('skip_connect', 2), + ('skip_connect', 2), + ('max_pool_3x3', 1) + ], + reduce_concat=[2, 3, 4, 5] +) + +PDARTS = Genotype( + normal=[ + ('skip_connect', 0), + ('dil_conv_3x3', 1), + ('skip_connect', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 0), + ('dil_conv_5x5', 4) + ], + normal_concat=range(2, 6), + reduce=[ + ('avg_pool_3x3', 0), + ('sep_conv_5x5', 1), + ('sep_conv_3x3', 0), + ('dil_conv_5x5', 2), + ('max_pool_3x3', 0), + ('dil_conv_3x3', 1), + ('dil_conv_3x3', 1), + ('dil_conv_5x5', 3) + ], + reduce_concat=range(2, 6) +) + +PCDARTS_C10 = Genotype( + normal=[ + ('sep_conv_3x3', 1), + ('skip_connect', 0), + ('sep_conv_3x3', 0), + ('dil_conv_3x3', 1), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 1), + ('avg_pool_3x3', 0), + ('dil_conv_3x3', 1) + ], + normal_concat=range(2, 6), + reduce=[ + ('sep_conv_5x5', 1), + ('max_pool_3x3', 0), + ('sep_conv_5x5', 1), + ('sep_conv_5x5', 2), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 2) + ], + reduce_concat=range(2, 6) +) + +PCDARTS_IN1K = Genotype( + normal=[ + ('skip_connect', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 0), + ('skip_connect', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 1), + ('dil_conv_5x5', 4) + ], + normal_concat=range(2, 6), + reduce=[ + ('sep_conv_3x3', 0), + ('skip_connect', 1), + ('dil_conv_5x5', 2), + ('max_pool_3x3', 1), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 1), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 3) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET_CLS = Genotype( + normal=[ + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 2), + ('sep_conv_5x5', 1), + ('sep_conv_3x3', 0) + ], + normal_concat=range(2, 6), + reduce=[ + ('max_pool_3x3', 0), + ('skip_connect', 1), + ('max_pool_3x3', 0), + ('dil_conv_5x5', 2), + ('max_pool_3x3', 0), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 4), + ('dil_conv_5x5', 3) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET_ROT = Genotype( + normal=[ + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1) + ], + normal_concat=range(2, 6), + reduce=[ + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 4), + ('sep_conv_5x5', 2) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET_COL = Genotype( + normal=[ + ('skip_connect', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 1), + ('skip_connect', 0), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 2) + ], + normal_concat=range(2, 6), + reduce=[ + ('max_pool_3x3', 0), + ('sep_conv_3x3', 1), + ('max_pool_3x3', 0), + ('sep_conv_3x3', 1), + ('max_pool_3x3', 0), + ('sep_conv_5x5', 3), + ('max_pool_3x3', 0), + ('sep_conv_3x3', 4) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET_JIG = Genotype( + normal=[ + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 1), + ('sep_conv_5x5', 0) + ], + normal_concat=range(2, 6), + reduce=[ + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 1) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET22K_CLS = Genotype( + normal=[ + ('sep_conv_3x3', 1), + ('skip_connect', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0) + ], + normal_concat=range(2, 6), + reduce=[ + ('max_pool_3x3', 0), + ('max_pool_3x3', 1), + ('dil_conv_5x5', 2), + ('max_pool_3x3', 0), + ('dil_conv_5x5', 3), + ('dil_conv_5x5', 2), + ('dil_conv_5x5', 4), + ('dil_conv_5x5', 3) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET22K_ROT = Genotype( + normal=[ + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1) + ], + normal_concat=range(2, 6), + reduce=[ + ('max_pool_3x3', 0), + ('sep_conv_5x5', 1), + ('dil_conv_5x5', 2), + ('sep_conv_5x5', 0), + ('dil_conv_5x5', 3), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 4), + ('sep_conv_3x3', 3) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET22K_COL = Genotype( + normal=[ + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 0) + ], + normal_concat=range(2, 6), + reduce=[ + ('max_pool_3x3', 0), + ('skip_connect', 1), + ('dil_conv_5x5', 2), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 4), + ('sep_conv_5x5', 1) + ], + reduce_concat=range(2, 6) +) + +UNNAS_IMAGENET22K_JIG = Genotype( + normal=[ + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 4) + ], + normal_concat=range(2, 6), + reduce=[ + ('sep_conv_5x5', 0), + ('skip_connect', 1), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 2), + ('sep_conv_5x5', 0), + ('sep_conv_5x5', 3), + ('sep_conv_5x5', 0), + ('sep_conv_5x5', 4) + ], + reduce_concat=range(2, 6) +) + +UNNAS_CITYSCAPES_SEG = Genotype( + normal=[ + ('skip_connect', 0), + ('sep_conv_5x5', 1), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1) + ], + normal_concat=range(2, 6), + reduce=[ + ('sep_conv_3x3', 0), + ('avg_pool_3x3', 1), + ('avg_pool_3x3', 1), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 2), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 4), + ('sep_conv_5x5', 2) + ], + reduce_concat=range(2, 6) +) + +UNNAS_CITYSCAPES_ROT = Genotype( + normal=[ + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 3), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0) + ], + normal_concat=range(2, 6), + reduce=[ + ('max_pool_3x3', 0), + ('sep_conv_5x5', 1), + ('sep_conv_5x5', 2), + ('sep_conv_5x5', 1), + ('sep_conv_5x5', 3), + ('dil_conv_5x5', 2), + ('sep_conv_5x5', 2), + ('sep_conv_5x5', 0) + ], + reduce_concat=range(2, 6) +) + +UNNAS_CITYSCAPES_COL = Genotype( + normal=[ + ('dil_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('skip_connect', 0), + ('sep_conv_5x5', 2), + ('dil_conv_3x3', 3), + ('skip_connect', 0), + ('skip_connect', 0), + ('sep_conv_3x3', 1) + ], + normal_concat=range(2, 6), + reduce=[ + ('avg_pool_3x3', 1), + ('avg_pool_3x3', 0), + ('avg_pool_3x3', 1), + ('avg_pool_3x3', 0), + ('avg_pool_3x3', 1), + ('avg_pool_3x3', 0), + ('avg_pool_3x3', 1), + ('skip_connect', 4) + ], + reduce_concat=range(2, 6) +) + +UNNAS_CITYSCAPES_JIG = Genotype( + normal=[ + ('dil_conv_5x5', 1), + ('sep_conv_5x5', 0), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 1), + ('sep_conv_3x3', 0), + ('sep_conv_3x3', 2), + ('sep_conv_3x3', 0), + ('dil_conv_5x5', 1) + ], + normal_concat=range(2, 6), + reduce=[ + ('avg_pool_3x3', 0), + ('skip_connect', 1), + ('dil_conv_5x5', 1), + ('dil_conv_5x5', 2), + ('dil_conv_5x5', 2), + ('dil_conv_5x5', 0), + ('dil_conv_5x5', 3), + ('dil_conv_5x5', 2) + ], + reduce_concat=range(2, 6) +) + + +# Supported genotypes +GENOTYPES = { + 'nas': NASNet, + 'pnas': PNASNet, + 'amoeba': AmoebaNet, + 'darts_v1': DARTS_V1, + 'darts_v2': DARTS_V2, + 'pdarts': PDARTS, + 'pcdarts_c10': PCDARTS_C10, + 'pcdarts_in1k': PCDARTS_IN1K, + 'unnas_imagenet_cls': UNNAS_IMAGENET_CLS, + 'unnas_imagenet_rot': UNNAS_IMAGENET_ROT, + 'unnas_imagenet_col': UNNAS_IMAGENET_COL, + 'unnas_imagenet_jig': UNNAS_IMAGENET_JIG, + 'unnas_imagenet22k_cls': UNNAS_IMAGENET22K_CLS, + 'unnas_imagenet22k_rot': UNNAS_IMAGENET22K_ROT, + 'unnas_imagenet22k_col': UNNAS_IMAGENET22K_COL, + 'unnas_imagenet22k_jig': UNNAS_IMAGENET22K_JIG, + 'unnas_cityscapes_seg': UNNAS_CITYSCAPES_SEG, + 'unnas_cityscapes_rot': UNNAS_CITYSCAPES_ROT, + 'unnas_cityscapes_col': UNNAS_CITYSCAPES_COL, + 'unnas_cityscapes_jig': UNNAS_CITYSCAPES_JIG, + 'custom': None, +} diff --git a/pycls/models/nas/nas.py b/pycls/models/nas/nas.py new file mode 100644 index 0000000..13339e3 --- /dev/null +++ b/pycls/models/nas/nas.py @@ -0,0 +1,299 @@ +#!/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. + +"""NAS network (adopted from DARTS).""" + +from torch.autograd import Variable + +import torch +import torch.nn as nn + +import pycls.core.logging as logging + +from pycls.core.config import cfg +from pycls.models.common import Preprocess +from pycls.models.common import Classifier +from pycls.models.nas.genotypes import GENOTYPES +from pycls.models.nas.genotypes import Genotype +from pycls.models.nas.operations import FactorizedReduce +from pycls.models.nas.operations import OPS +from pycls.models.nas.operations import ReLUConvBN +from pycls.models.nas.operations import Identity + + +logger = logging.get_logger(__name__) + + +def drop_path(x, drop_prob): + """Drop path (ported from DARTS).""" + if drop_prob > 0.: + keep_prob = 1.-drop_prob + mask = Variable( + torch.cuda.FloatTensor(x.size(0), 1, 1, 1).bernoulli_(keep_prob) + ) + x.div_(keep_prob) + x.mul_(mask) + return x + + +class Cell(nn.Module): + """NAS cell (ported from DARTS).""" + + def __init__(self, genotype, C_prev_prev, C_prev, C, reduction, reduction_prev): + super(Cell, self).__init__() + logger.info('{}, {}, {}'.format(C_prev_prev, C_prev, C)) + + if reduction_prev: + self.preprocess0 = FactorizedReduce(C_prev_prev, C) + else: + self.preprocess0 = ReLUConvBN(C_prev_prev, C, 1, 1, 0) + self.preprocess1 = ReLUConvBN(C_prev, C, 1, 1, 0) + + if reduction: + op_names, indices = zip(*genotype.reduce) + concat = genotype.reduce_concat + else: + op_names, indices = zip(*genotype.normal) + concat = genotype.normal_concat + self._compile(C, op_names, indices, concat, reduction) + + def _compile(self, C, op_names, indices, concat, reduction): + assert len(op_names) == len(indices) + self._steps = len(op_names) // 2 + self._concat = concat + self.multiplier = len(concat) + + self._ops = nn.ModuleList() + for name, index in zip(op_names, indices): + stride = 2 if reduction and index < 2 else 1 + op = OPS[name](C, stride, True) + self._ops += [op] + self._indices = indices + + def forward(self, s0, s1, drop_prob): + s0 = self.preprocess0(s0) + s1 = self.preprocess1(s1) + + states = [s0, s1] + for i in range(self._steps): + h1 = states[self._indices[2*i]] + h2 = states[self._indices[2*i+1]] + op1 = self._ops[2*i] + op2 = self._ops[2*i+1] + h1 = op1(h1) + h2 = op2(h2) + if self.training and drop_prob > 0.: + if not isinstance(op1, Identity): + h1 = drop_path(h1, drop_prob) + if not isinstance(op2, Identity): + h2 = drop_path(h2, drop_prob) + s = h1 + h2 + states += [s] + return torch.cat([states[i] for i in self._concat], dim=1) + + +class AuxiliaryHeadCIFAR(nn.Module): + + def __init__(self, C, num_classes): + """assuming input size 8x8""" + super(AuxiliaryHeadCIFAR, self).__init__() + self.features = nn.Sequential( + nn.ReLU(inplace=True), + nn.AvgPool2d(5, stride=3, padding=0, count_include_pad=False), # image size = 2 x 2 + nn.Conv2d(C, 128, 1, bias=False), + nn.BatchNorm2d(128), + nn.ReLU(inplace=True), + nn.Conv2d(128, 768, 2, bias=False), + nn.BatchNorm2d(768), + nn.ReLU(inplace=True) + ) + self.classifier = nn.Linear(768, num_classes) + + def forward(self, x): + x = self.features(x) + x = self.classifier(x.view(x.size(0),-1)) + return x + + +class AuxiliaryHeadImageNet(nn.Module): + + def __init__(self, C, num_classes): + """assuming input size 14x14""" + super(AuxiliaryHeadImageNet, self).__init__() + self.features = nn.Sequential( + nn.ReLU(inplace=True), + nn.AvgPool2d(5, stride=2, padding=0, count_include_pad=False), + nn.Conv2d(C, 128, 1, bias=False), + nn.BatchNorm2d(128), + nn.ReLU(inplace=True), + nn.Conv2d(128, 768, 2, bias=False), + # NOTE: This batchnorm was omitted in my earlier implementation due to a typo. + # Commenting it out for consistency with the experiments in the paper. + # nn.BatchNorm2d(768), + nn.ReLU(inplace=True) + ) + self.classifier = nn.Linear(768, num_classes) + + def forward(self, x): + x = self.features(x) + x = self.classifier(x.view(x.size(0),-1)) + return x + + +class NetworkCIFAR(nn.Module): + """CIFAR network (ported from DARTS).""" + + def __init__(self, C, num_classes, layers, auxiliary, genotype): + super(NetworkCIFAR, self).__init__() + self._layers = layers + self._auxiliary = auxiliary + + stem_multiplier = 3 + C_curr = stem_multiplier*C + self.stem = nn.Sequential( + nn.Conv2d(cfg.MODEL.INPUT_CHANNELS, C_curr, 3, padding=1, bias=False), + nn.BatchNorm2d(C_curr) + ) + + C_prev_prev, C_prev, C_curr = C_curr, C_curr, C + self.cells = nn.ModuleList() + reduction_prev = False + for i in range(layers): + if i in [layers//3, 2*layers//3]: + C_curr *= 2 + reduction = True + else: + reduction = False + cell = Cell(genotype, C_prev_prev, C_prev, C_curr, reduction, reduction_prev) + reduction_prev = reduction + self.cells += [cell] + C_prev_prev, C_prev = C_prev, cell.multiplier*C_curr + if i == 2*layers//3: + C_to_auxiliary = C_prev + + if auxiliary: + self.auxiliary_head = AuxiliaryHeadCIFAR(C_to_auxiliary, num_classes) + self.classifier = Classifier(C_prev, num_classes) + + def forward(self, input): + input = Preprocess(input) + logits_aux = None + s0 = s1 = self.stem(input) + for i, cell in enumerate(self.cells): + s0, s1 = s1, cell(s0, s1, self.drop_path_prob) + if i == 2*self._layers//3: + if self._auxiliary and self.training: + logits_aux = self.auxiliary_head(s1) + logits = self.classifier(s1, input.shape[2:]) + if self._auxiliary and self.training: + return logits, logits_aux + return logits + + +class NetworkImageNet(nn.Module): + """ImageNet network (ported from DARTS).""" + + def __init__(self, C, num_classes, layers, auxiliary, genotype): + super(NetworkImageNet, self).__init__() + self._layers = layers + self._auxiliary = auxiliary + + self.stem0 = nn.Sequential( + nn.Conv2d(cfg.MODEL.INPUT_CHANNELS, C // 2, kernel_size=3, stride=2, padding=1, bias=False), + nn.BatchNorm2d(C // 2), + nn.ReLU(inplace=True), + nn.Conv2d(C // 2, C, 3, stride=2, padding=1, bias=False), + nn.BatchNorm2d(C), + ) + + self.stem1 = nn.Sequential( + nn.ReLU(inplace=True), + nn.Conv2d(C, C, 3, stride=2, padding=1, bias=False), + nn.BatchNorm2d(C), + ) + + C_prev_prev, C_prev, C_curr = C, C, C + + self.cells = nn.ModuleList() + reduction_prev = True + reduction_layers = [layers//3] if cfg.TASK == 'seg' else [layers//3, 2*layers//3] + for i in range(layers): + if i in reduction_layers: + C_curr *= 2 + reduction = True + else: + reduction = False + cell = Cell(genotype, C_prev_prev, C_prev, C_curr, reduction, reduction_prev) + reduction_prev = reduction + self.cells += [cell] + C_prev_prev, C_prev = C_prev, cell.multiplier * C_curr + if i == 2 * layers // 3: + C_to_auxiliary = C_prev + + if auxiliary: + self.auxiliary_head = AuxiliaryHeadImageNet(C_to_auxiliary, num_classes) + self.classifier = Classifier(C_prev, num_classes) + + def forward(self, input): + input = Preprocess(input) + logits_aux = None + s0 = self.stem0(input) + s1 = self.stem1(s0) + for i, cell in enumerate(self.cells): + s0, s1 = s1, cell(s0, s1, self.drop_path_prob) + if i == 2 * self._layers // 3: + if self._auxiliary and self.training: + logits_aux = self.auxiliary_head(s1) + logits = self.classifier(s1, input.shape[2:]) + if self._auxiliary and self.training: + return logits, logits_aux + return logits + + +class NAS(nn.Module): + """NAS net wrapper (delegates to nets from DARTS).""" + + def __init__(self): + assert cfg.TRAIN.DATASET in ['cifar10', 'imagenet', 'cityscapes'], \ + 'Training on {} is not supported'.format(cfg.TRAIN.DATASET) + assert cfg.TEST.DATASET in ['cifar10', 'imagenet', 'cityscapes'], \ + 'Testing on {} is not supported'.format(cfg.TEST.DATASET) + assert cfg.NAS.GENOTYPE in GENOTYPES, \ + 'Genotype {} not supported'.format(cfg.NAS.GENOTYPE) + super(NAS, self).__init__() + logger.info('Constructing NAS: {}'.format(cfg.NAS)) + # Use a custom or predefined genotype + if cfg.NAS.GENOTYPE == 'custom': + genotype = Genotype( + normal=cfg.NAS.CUSTOM_GENOTYPE[0], + normal_concat=cfg.NAS.CUSTOM_GENOTYPE[1], + reduce=cfg.NAS.CUSTOM_GENOTYPE[2], + reduce_concat=cfg.NAS.CUSTOM_GENOTYPE[3], + ) + else: + genotype = GENOTYPES[cfg.NAS.GENOTYPE] + # Determine the network constructor for dataset + if 'cifar' in cfg.TRAIN.DATASET: + net_ctor = NetworkCIFAR + else: + net_ctor = NetworkImageNet + # Construct the network + self.net_ = net_ctor( + C=cfg.NAS.WIDTH, + num_classes=cfg.MODEL.NUM_CLASSES, + layers=cfg.NAS.DEPTH, + auxiliary=cfg.NAS.AUX, + genotype=genotype + ) + # Drop path probability (set / annealed based on epoch) + self.net_.drop_path_prob = 0.0 + + def set_drop_path_prob(self, drop_path_prob): + self.net_.drop_path_prob = drop_path_prob + + def forward(self, x): + return self.net_.forward(x) diff --git a/pycls/models/nas/operations.py b/pycls/models/nas/operations.py new file mode 100644 index 0000000..ead55ca --- /dev/null +++ b/pycls/models/nas/operations.py @@ -0,0 +1,201 @@ +#!/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. + + +"""NAS ops (adopted from DARTS).""" + +import torch +import torch.nn as nn + + +OPS = { + 'none': lambda C, stride, affine: + Zero(stride), + 'avg_pool_2x2': lambda C, stride, affine: + nn.AvgPool2d(2, stride=stride, padding=0, count_include_pad=False), + 'avg_pool_3x3': lambda C, stride, affine: + nn.AvgPool2d(3, stride=stride, padding=1, count_include_pad=False), + 'avg_pool_5x5': lambda C, stride, affine: + nn.AvgPool2d(5, stride=stride, padding=2, count_include_pad=False), + 'max_pool_2x2': lambda C, stride, affine: + nn.MaxPool2d(2, stride=stride, padding=0), + 'max_pool_3x3': lambda C, stride, affine: + nn.MaxPool2d(3, stride=stride, padding=1), + 'max_pool_5x5': lambda C, stride, affine: + nn.MaxPool2d(5, stride=stride, padding=2), + 'max_pool_7x7': lambda C, stride, affine: + nn.MaxPool2d(7, stride=stride, padding=3), + 'skip_connect': lambda C, stride, affine: + Identity() if stride == 1 else FactorizedReduce(C, C, affine=affine), + 'conv_1x1': lambda C, stride, affine: + nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d(C, C, 1, stride=stride, padding=0, bias=False), + nn.BatchNorm2d(C, affine=affine) + ), + 'conv_3x3': lambda C, stride, affine: + nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d(C, C, 3, stride=stride, padding=1, bias=False), + nn.BatchNorm2d(C, affine=affine) + ), + 'sep_conv_3x3': lambda C, stride, affine: + SepConv(C, C, 3, stride, 1, affine=affine), + 'sep_conv_5x5': lambda C, stride, affine: + SepConv(C, C, 5, stride, 2, affine=affine), + 'sep_conv_7x7': lambda C, stride, affine: + SepConv(C, C, 7, stride, 3, affine=affine), + 'dil_conv_3x3': lambda C, stride, affine: + DilConv(C, C, 3, stride, 2, 2, affine=affine), + 'dil_conv_5x5': lambda C, stride, affine: + DilConv(C, C, 5, stride, 4, 2, affine=affine), + 'dil_sep_conv_3x3': lambda C, stride, affine: + DilSepConv(C, C, 3, stride, 2, 2, affine=affine), + 'conv_3x1_1x3': lambda C, stride, affine: + nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d(C, C, (1,3), stride=(1, stride), padding=(0, 1), bias=False), + nn.Conv2d(C, C, (3,1), stride=(stride, 1), padding=(1, 0), bias=False), + nn.BatchNorm2d(C, affine=affine) + ), + 'conv_7x1_1x7': lambda C, stride, affine: + nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d(C, C, (1,7), stride=(1, stride), padding=(0, 3), bias=False), + nn.Conv2d(C, C, (7,1), stride=(stride, 1), padding=(3, 0), bias=False), + nn.BatchNorm2d(C, affine=affine) + ), +} + + +class ReLUConvBN(nn.Module): + + def __init__(self, C_in, C_out, kernel_size, stride, padding, affine=True): + super(ReLUConvBN, self).__init__() + self.op = nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d( + C_in, C_out, kernel_size, stride=stride, + padding=padding, bias=False + ), + nn.BatchNorm2d(C_out, affine=affine) + ) + + def forward(self, x): + return self.op(x) + + +class DilConv(nn.Module): + + def __init__( + self, C_in, C_out, kernel_size, stride, padding, dilation, affine=True + ): + super(DilConv, self).__init__() + self.op = nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d( + C_in, C_in, kernel_size=kernel_size, stride=stride, + padding=padding, dilation=dilation, groups=C_in, bias=False + ), + nn.Conv2d(C_in, C_out, kernel_size=1, padding=0, bias=False), + nn.BatchNorm2d(C_out, affine=affine), + ) + + def forward(self, x): + return self.op(x) + + +class SepConv(nn.Module): + + def __init__(self, C_in, C_out, kernel_size, stride, padding, affine=True): + super(SepConv, self).__init__() + self.op = nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d( + C_in, C_in, kernel_size=kernel_size, stride=stride, + padding=padding, groups=C_in, bias=False + ), + nn.Conv2d(C_in, C_in, kernel_size=1, padding=0, bias=False), + nn.BatchNorm2d(C_in, affine=affine), + nn.ReLU(inplace=False), + nn.Conv2d( + C_in, C_in, kernel_size=kernel_size, stride=1, + padding=padding, groups=C_in, bias=False + ), + nn.Conv2d(C_in, C_out, kernel_size=1, padding=0, bias=False), + nn.BatchNorm2d(C_out, affine=affine), + ) + + def forward(self, x): + return self.op(x) + + +class DilSepConv(nn.Module): + + def __init__( + self, C_in, C_out, kernel_size, stride, padding, dilation, affine=True + ): + super(DilSepConv, self).__init__() + self.op = nn.Sequential( + nn.ReLU(inplace=False), + nn.Conv2d( + C_in, C_in, kernel_size=kernel_size, stride=stride, + padding=padding, dilation=dilation, groups=C_in, bias=False + ), + nn.Conv2d(C_in, C_in, kernel_size=1, padding=0, bias=False), + nn.BatchNorm2d(C_in, affine=affine), + nn.ReLU(inplace=False), + nn.Conv2d( + C_in, C_in, kernel_size=kernel_size, stride=1, + padding=padding, dilation=dilation, groups=C_in, bias=False + ), + nn.Conv2d(C_in, C_out, kernel_size=1, padding=0, bias=False), + nn.BatchNorm2d(C_out, affine=affine), + ) + + def forward(self, x): + return self.op(x) + + +class Identity(nn.Module): + + def __init__(self): + super(Identity, self).__init__() + + def forward(self, x): + return x + + +class Zero(nn.Module): + + def __init__(self, stride): + super(Zero, self).__init__() + self.stride = stride + + def forward(self, x): + if self.stride == 1: + return x.mul(0.) + return x[:,:,::self.stride,::self.stride].mul(0.) + + +class FactorizedReduce(nn.Module): + + def __init__(self, C_in, C_out, affine=True): + super(FactorizedReduce, self).__init__() + assert C_out % 2 == 0 + self.relu = nn.ReLU(inplace=False) + self.conv_1 = nn.Conv2d(C_in, C_out // 2, 1, stride=2, padding=0, bias=False) + self.conv_2 = nn.Conv2d(C_in, C_out // 2, 1, stride=2, padding=0, bias=False) + self.bn = nn.BatchNorm2d(C_out, affine=affine) + self.pad = nn.ConstantPad2d((0, 1, 0, 1), 0) + + def forward(self, x): + x = self.relu(x) + y = self.pad(x) + out = torch.cat([self.conv_1(x), self.conv_2(y[:,:,1:,1:])], dim=1) + out = self.bn(out) + return out diff --git a/pycls/models/regnet.py b/pycls/models/regnet.py new file mode 100644 index 0000000..62c9b69 --- /dev/null +++ b/pycls/models/regnet.py @@ -0,0 +1,89 @@ +#!/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. + +"""RegNet models.""" + +import numpy as np +from pycls.core.config import cfg +from pycls.models.anynet import AnyNet + + +def quantize_float(f, q): + """Converts a float to closest non-zero int divisible by q.""" + return int(round(f / q) * q) + + +def adjust_ws_gs_comp(ws, bms, gs): + """Adjusts the compatibility of widths and groups.""" + ws_bot = [int(w * b) for w, b in zip(ws, bms)] + gs = [min(g, w_bot) for g, w_bot in zip(gs, ws_bot)] + ws_bot = [quantize_float(w_bot, g) for w_bot, g in zip(ws_bot, gs)] + ws = [int(w_bot / b) for w_bot, b in zip(ws_bot, bms)] + return ws, gs + + +def get_stages_from_blocks(ws, rs): + """Gets ws/ds of network at each stage from per block values.""" + ts_temp = zip(ws + [0], [0] + ws, rs + [0], [0] + rs) + ts = [w != wp or r != rp for w, wp, r, rp in ts_temp] + s_ws = [w for w, t in zip(ws, ts[:-1]) if t] + s_ds = np.diff([d for d, t in zip(range(len(ts)), ts) if t]).tolist() + return s_ws, s_ds + + +def generate_regnet(w_a, w_0, w_m, d, q=8): + """Generates per block ws from RegNet parameters.""" + assert w_a >= 0 and w_0 > 0 and w_m > 1 and w_0 % q == 0 + ws_cont = np.arange(d) * w_a + w_0 + ks = np.round(np.log(ws_cont / w_0) / np.log(w_m)) + ws = w_0 * np.power(w_m, ks) + ws = np.round(np.divide(ws, q)) * q + num_stages, max_stage = len(np.unique(ws)), ks.max() + 1 + ws, ws_cont = ws.astype(int).tolist(), ws_cont.tolist() + return ws, num_stages, max_stage, ws_cont + + +class RegNet(AnyNet): + """RegNet model.""" + + @staticmethod + def get_args(): + """Convert RegNet to AnyNet parameter format.""" + # Generate RegNet ws per block + w_a, w_0, w_m, d = cfg.REGNET.WA, cfg.REGNET.W0, cfg.REGNET.WM, cfg.REGNET.DEPTH + ws, num_stages, _, _ = generate_regnet(w_a, w_0, w_m, d) + # Convert to per stage format + s_ws, s_ds = get_stages_from_blocks(ws, ws) + # Use the same gw, bm and ss for each stage + s_gs = [cfg.REGNET.GROUP_W for _ in range(num_stages)] + s_bs = [cfg.REGNET.BOT_MUL for _ in range(num_stages)] + s_ss = [cfg.REGNET.STRIDE for _ in range(num_stages)] + # Adjust the compatibility of ws and gws + s_ws, s_gs = adjust_ws_gs_comp(s_ws, s_bs, s_gs) + # Get AnyNet arguments defining the RegNet + return { + "stem_type": cfg.REGNET.STEM_TYPE, + "stem_w": cfg.REGNET.STEM_W, + "block_type": cfg.REGNET.BLOCK_TYPE, + "ds": s_ds, + "ws": s_ws, + "ss": s_ss, + "bms": s_bs, + "gws": s_gs, + "se_r": cfg.REGNET.SE_R if cfg.REGNET.SE_ON else None, + "nc": cfg.MODEL.NUM_CLASSES, + } + + def __init__(self): + kwargs = RegNet.get_args() + super(RegNet, self).__init__(**kwargs) + + @staticmethod + def complexity(cx, **kwargs): + """Computes model complexity. If you alter the model, make sure to update.""" + kwargs = RegNet.get_args() if not kwargs else kwargs + return AnyNet.complexity(cx, **kwargs) diff --git a/pycls/models/resnet.py b/pycls/models/resnet.py new file mode 100644 index 0000000..41cfaff --- /dev/null +++ b/pycls/models/resnet.py @@ -0,0 +1,280 @@ +#!/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. + +"""ResNe(X)t models.""" + +import pycls.core.net as net +import torch.nn as nn +from pycls.core.config import cfg + + +# Stage depths for ImageNet models +_IN_STAGE_DS = {50: (3, 4, 6, 3), 101: (3, 4, 23, 3), 152: (3, 8, 36, 3)} + + +def get_trans_fun(name): + """Retrieves the transformation function by name.""" + trans_funs = { + "basic_transform": BasicTransform, + "bottleneck_transform": BottleneckTransform, + } + err_str = "Transformation function '{}' not supported" + assert name in trans_funs.keys(), err_str.format(name) + return trans_funs[name] + + +class ResHead(nn.Module): + """ResNet head: AvgPool, 1x1.""" + + def __init__(self, w_in, nc): + super(ResHead, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) + self.fc = nn.Linear(w_in, nc, bias=True) + + def forward(self, x): + x = self.avg_pool(x) + x = x.view(x.size(0), -1) + x = self.fc(x) + return x + + @staticmethod + def complexity(cx, w_in, nc): + cx["h"], cx["w"] = 1, 1 + cx = net.complexity_conv2d(cx, w_in, nc, 1, 1, 0, bias=True) + return cx + + +class BasicTransform(nn.Module): + """Basic transformation: 3x3, BN, ReLU, 3x3, BN.""" + + def __init__(self, w_in, w_out, stride, w_b=None, num_gs=1): + err_str = "Basic transform does not support w_b and num_gs options" + assert w_b is None and num_gs == 1, err_str + super(BasicTransform, self).__init__() + self.a = nn.Conv2d(w_in, w_out, 3, stride=stride, padding=1, bias=False) + self.a_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.a_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + self.b = nn.Conv2d(w_out, w_out, 3, stride=1, padding=1, bias=False) + self.b_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.b_bn.final_bn = True + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, w_b=None, num_gs=1): + err_str = "Basic transform does not support w_b and num_gs options" + assert w_b is None and num_gs == 1, err_str + cx = net.complexity_conv2d(cx, w_in, w_out, 3, stride, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + cx = net.complexity_conv2d(cx, w_out, w_out, 3, 1, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class BottleneckTransform(nn.Module): + """Bottleneck transformation: 1x1, BN, ReLU, 3x3, BN, ReLU, 1x1, BN.""" + + def __init__(self, w_in, w_out, stride, w_b, num_gs): + super(BottleneckTransform, self).__init__() + # MSRA -> stride=2 is on 1x1; TH/C2 -> stride=2 is on 3x3 + (s1, s3) = (stride, 1) if cfg.RESNET.STRIDE_1X1 else (1, stride) + self.a = nn.Conv2d(w_in, w_b, 1, stride=s1, padding=0, bias=False) + self.a_bn = nn.BatchNorm2d(w_b, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.a_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + self.b = nn.Conv2d(w_b, w_b, 3, stride=s3, padding=1, groups=num_gs, bias=False) + self.b_bn = nn.BatchNorm2d(w_b, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.b_relu = nn.ReLU(inplace=cfg.MEM.RELU_INPLACE) + self.c = nn.Conv2d(w_b, w_out, 1, stride=1, padding=0, bias=False) + self.c_bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.c_bn.final_bn = True + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, w_b, num_gs): + (s1, s3) = (stride, 1) if cfg.RESNET.STRIDE_1X1 else (1, stride) + cx = net.complexity_conv2d(cx, w_in, w_b, 1, s1, 0) + cx = net.complexity_batchnorm2d(cx, w_b) + cx = net.complexity_conv2d(cx, w_b, w_b, 3, s3, 1, num_gs) + cx = net.complexity_batchnorm2d(cx, w_b) + cx = net.complexity_conv2d(cx, w_b, w_out, 1, 1, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class ResBlock(nn.Module): + """Residual block: x + F(x).""" + + def __init__(self, w_in, w_out, stride, trans_fun, w_b=None, num_gs=1): + super(ResBlock, self).__init__() + # Use skip connection with projection if shape changes + self.proj_block = (w_in != w_out) or (stride != 1) + if self.proj_block: + self.proj = nn.Conv2d(w_in, w_out, 1, stride=stride, padding=0, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.f = trans_fun(w_in, w_out, stride, w_b, num_gs) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + + def forward(self, x): + if self.proj_block: + x = self.bn(self.proj(x)) + self.f(x) + else: + x = x + self.f(x) + x = self.relu(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, trans_fun, w_b, num_gs): + proj_block = (w_in != w_out) or (stride != 1) + if proj_block: + h, w = cx["h"], cx["w"] + cx = net.complexity_conv2d(cx, w_in, w_out, 1, stride, 0) + cx = net.complexity_batchnorm2d(cx, w_out) + cx["h"], cx["w"] = h, w # parallel branch + cx = trans_fun.complexity(cx, w_in, w_out, stride, w_b, num_gs) + return cx + + +class ResStage(nn.Module): + """Stage of ResNet.""" + + def __init__(self, w_in, w_out, stride, d, w_b=None, num_gs=1): + super(ResStage, self).__init__() + for i in range(d): + b_stride = stride if i == 0 else 1 + b_w_in = w_in if i == 0 else w_out + trans_fun = get_trans_fun(cfg.RESNET.TRANS_FUN) + res_block = ResBlock(b_w_in, w_out, b_stride, trans_fun, w_b, num_gs) + self.add_module("b{}".format(i + 1), res_block) + + def forward(self, x): + for block in self.children(): + x = block(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out, stride, d, w_b=None, num_gs=1): + for i in range(d): + b_stride = stride if i == 0 else 1 + b_w_in = w_in if i == 0 else w_out + trans_f = get_trans_fun(cfg.RESNET.TRANS_FUN) + cx = ResBlock.complexity(cx, b_w_in, w_out, b_stride, trans_f, w_b, num_gs) + return cx + + +class ResStemCifar(nn.Module): + """ResNet stem for CIFAR: 3x3, BN, ReLU.""" + + def __init__(self, w_in, w_out): + super(ResStemCifar, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 3, stride=1, padding=1, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out): + cx = net.complexity_conv2d(cx, w_in, w_out, 3, 1, 1) + cx = net.complexity_batchnorm2d(cx, w_out) + return cx + + +class ResStemIN(nn.Module): + """ResNet stem for ImageNet: 7x7, BN, ReLU, MaxPool.""" + + def __init__(self, w_in, w_out): + super(ResStemIN, self).__init__() + self.conv = nn.Conv2d(w_in, w_out, 7, stride=2, padding=3, bias=False) + self.bn = nn.BatchNorm2d(w_out, eps=cfg.BN.EPS, momentum=cfg.BN.MOM) + self.relu = nn.ReLU(cfg.MEM.RELU_INPLACE) + self.pool = nn.MaxPool2d(3, stride=2, padding=1) + + def forward(self, x): + for layer in self.children(): + x = layer(x) + return x + + @staticmethod + def complexity(cx, w_in, w_out): + cx = net.complexity_conv2d(cx, w_in, w_out, 7, 2, 3) + cx = net.complexity_batchnorm2d(cx, w_out) + cx = net.complexity_maxpool2d(cx, 3, 2, 1) + return cx + + +class ResNet(nn.Module): + """ResNet model.""" + + def __init__(self): + datasets = ["cifar10", "imagenet"] + err_str = "Dataset {} is not supported" + assert cfg.TRAIN.DATASET in datasets, err_str.format(cfg.TRAIN.DATASET) + assert cfg.TEST.DATASET in datasets, err_str.format(cfg.TEST.DATASET) + super(ResNet, self).__init__() + if "cifar" in cfg.TRAIN.DATASET: + self._construct_cifar() + else: + self._construct_imagenet() + self.apply(net.init_weights) + + def _construct_cifar(self): + err_str = "Model depth should be of the format 6n + 2 for cifar" + assert (cfg.MODEL.DEPTH - 2) % 6 == 0, err_str + d = int((cfg.MODEL.DEPTH - 2) / 6) + self.stem = ResStemCifar(3, 16) + self.s1 = ResStage(16, 16, stride=1, d=d) + self.s2 = ResStage(16, 32, stride=2, d=d) + self.s3 = ResStage(32, 64, stride=2, d=d) + self.head = ResHead(64, nc=cfg.MODEL.NUM_CLASSES) + + def _construct_imagenet(self): + g, gw = cfg.RESNET.NUM_GROUPS, cfg.RESNET.WIDTH_PER_GROUP + (d1, d2, d3, d4) = _IN_STAGE_DS[cfg.MODEL.DEPTH] + w_b = gw * g + self.stem = ResStemIN(3, 64) + self.s1 = ResStage(64, 256, stride=1, d=d1, w_b=w_b, num_gs=g) + self.s2 = ResStage(256, 512, stride=2, d=d2, w_b=w_b * 2, num_gs=g) + self.s3 = ResStage(512, 1024, stride=2, d=d3, w_b=w_b * 4, num_gs=g) + self.s4 = ResStage(1024, 2048, stride=2, d=d4, w_b=w_b * 8, num_gs=g) + self.head = ResHead(2048, nc=cfg.MODEL.NUM_CLASSES) + + def forward(self, x): + for module in self.children(): + x = module(x) + return x + + @staticmethod + def complexity(cx): + """Computes model complexity. If you alter the model, make sure to update.""" + if "cifar" in cfg.TRAIN.DATASET: + d = int((cfg.MODEL.DEPTH - 2) / 6) + cx = ResStemCifar.complexity(cx, 3, 16) + cx = ResStage.complexity(cx, 16, 16, stride=1, d=d) + cx = ResStage.complexity(cx, 16, 32, stride=2, d=d) + cx = ResStage.complexity(cx, 32, 64, stride=2, d=d) + cx = ResHead.complexity(cx, 64, nc=cfg.MODEL.NUM_CLASSES) + else: + g, gw = cfg.RESNET.NUM_GROUPS, cfg.RESNET.WIDTH_PER_GROUP + (d1, d2, d3, d4) = _IN_STAGE_DS[cfg.MODEL.DEPTH] + w_b = gw * g + cx = ResStemIN.complexity(cx, 3, 64) + cx = ResStage.complexity(cx, 64, 256, 1, d=d1, w_b=w_b, num_gs=g) + cx = ResStage.complexity(cx, 256, 512, 2, d=d2, w_b=w_b * 2, num_gs=g) + cx = ResStage.complexity(cx, 512, 1024, 2, d=d3, w_b=w_b * 4, num_gs=g) + cx = ResStage.complexity(cx, 1024, 2048, 2, d=d4, w_b=w_b * 8, num_gs=g) + cx = ResHead.complexity(cx, 2048, nc=cfg.MODEL.NUM_CLASSES) + return cx diff --git a/reproduce.sh b/reproduce.sh deleted file mode 100755 index bcbe672..0000000 --- a/reproduce.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -python search.py --dataset cifar10 --data_loc '../datasets/cifar10' --n_runs $1 --n_samples 10 -python search.py --dataset cifar10 --trainval --data_loc '../datasets/cifar10' --n_runs $1 --n_samples 10 -python search.py --dataset cifar100 --data_loc '../datasets/cifar100' --n_runs $1 --n_samples 10 -python search.py --dataset ImageNet16-120 --data_loc '../datasets/ImageNet16' --n_runs $1 --n_samples 10 - -python search.py --dataset cifar10 --data_loc '../datasets/cifar10' --n_runs $1 --n_samples 100 -python search.py --dataset cifar10 --trainval --data_loc '../datasets/cifar10' --n_runs $1 --n_samples 100 -python search.py --dataset cifar100 --data_loc '../datasets/cifar100' --n_runs $1 --n_samples 100 -python search.py --dataset ImageNet16-120 --data_loc '../datasets/ImageNet16' --n_runs $1 --n_samples 100 - -python process_results.py --n_runs $1 diff --git a/results/arch_score_acc.pd b/results/arch_score_acc.pd deleted file mode 100644 index 137a3079576be76ceb14781ff5e103a110893a7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2132531 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

R34SbkGM^)?YoVpZ(akyys6|TtEH&{58+b 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≫p4t= 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⩾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 0).float() + K = x @ x.t() + K2 = (1.-x) @ (1.-x.t()) + network.K = network.K + K.cpu().numpy() + K2.cpu().numpy() + except: + pass + + + def counting_backward_hook(module, inp, out): + module.visited_backwards = True + + + for name, module in network.named_modules(): + if 'ReLU' in str(type(module)): + #hooks[name] = module.register_forward_hook(counting_hook) + module.register_forward_hook(counting_forward_hook) + module.register_backward_hook(counting_backward_hook) + + network = network.to(device) + random.seed(args.seed) + np.random.seed(args.seed) + torch.manual_seed(args.seed) + s = [] + for j in range(args.maxofn): + data_iterator = iter(train_loader) + x, target = next(data_iterator) + x2 = torch.clone(x) + x2 = x2.to(device) + x, target = x.to(device), target.to(device) + jacobs, labels, y, out = get_batch_jacobian(network, x, target, device, args) + + + + + + + + if 'hook_' in args.score: + network(x2.to(device)) + s.append(get_score_func(args.score)(network.K, target)) + else: + s.append(get_score_func(args.score)(jacobs, labels)) + scores[i] = np.mean(s) + accs[i] = searchspace.get_final_accuracy(uid, acc_type, args.trainval) + accs_ = accs[~np.isnan(scores)] + scores_ = scores[~np.isnan(scores)] + numnan = np.isnan(scores).sum() + tau, p = stats.kendalltau(accs_[:max(i-numnan, 1)], scores_[:max(i-numnan, 1)]) + print(f'{tau}') + if i % 1000 == 0: + np.save(filename, scores) + np.save(accfilename, accs) + except Exception as e: + print(e) + accs[i] = searchspace.get_final_accuracy(uid, acc_type, args.trainval) + scores[i] = np.nan +np.save(filename, scores) +np.save(accfilename, accs) diff --git a/scorehook.sh b/scorehook.sh new file mode 100644 index 0000000..3a3a126 --- /dev/null +++ b/scorehook.sh @@ -0,0 +1,32 @@ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nasbench201 --batch_size 128 --GPU 3 --dataset cifar10 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nasbench201 --batch_size 128 --GPU 3 --dataset cifar100 --data_loc ../cifar100/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nasbench201 --batch_size 128 --GPU 3 --dataset ImageNet16-120 --data_loc ../imagenet16/Imagenet16/ + + +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_pnas --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_enas --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_darts --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_darts_fix-w-d --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_nasnet --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_amoeba --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_resnet --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_resnext-a --batch_size 128 --GPU 3 +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_resnext-b --batch_size 128 --GPU 3 + + + +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace amoeba_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_amoeba_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_darts_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_nasnet_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_pnas_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_enas_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nds_resnext-a_in --batch_size 128 --GPU 3 --dataset imagenette2 --data_loc ../imagenette2/ + + + +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nasbench201 --batch_size 128 --GPU 3 --dataset cifar100 --data_loc ../cifar100/ +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nasbench201 --batch_size 128 --GPU 3 --dataset ImageNet16-120 --data_loc ../imagenet16/Imagenet16/ + +python score_networks.py --trainval --augtype none --repeat 1 --score hook_logdet --sigma 0.05 --nasspace nasbench101 --batch_size 128 --GPU 3 --api_loc ../nasbench_only108.tfrecord + diff --git a/scores.py b/scores.py new file mode 100644 index 0000000..c5ea443 --- /dev/null +++ b/scores.py @@ -0,0 +1,21 @@ +import numpy as np +import torch + + + + +def hooklogdet(K, labels=None): + s, ld = np.linalg.slogdet(K) + return ld + +def random_score(jacob, label=None): + return np.random.normal() + + +_scores = { + 'hook_logdet': hooklogdet, + 'random': random_score + } + +def get_score_func(score_name): + return _scores[score_name] diff --git a/search.py b/search.py index 8bc4205..b875a67 100644 --- a/search.py +++ b/search.py @@ -1,35 +1,49 @@ -import os -import time import argparse +import nasspace +import datasets import random import numpy as np +import torch +import os +from scores import get_score_func +from sklearn.metrics.pairwise import cosine_similarity from tqdm import trange from statistics import mean +import time +from utils import add_dropout + parser = argparse.ArgumentParser(description='NAS Without Training') -parser.add_argument('--data_loc', default='../datasets/cifar', type=str, help='dataset folder') -parser.add_argument('--api_loc', default='../datasets/NAS-Bench-201-v1_1-096897.pth', +parser.add_argument('--data_loc', default='../cifardata/', type=str, help='dataset folder') +parser.add_argument('--api_loc', default='../NAS-Bench-201-v1_0-e61699.pth', type=str, help='path to API') -parser.add_argument('--save_loc', default='results', type=str, help='folder to save results') -parser.add_argument('--batch_size', default=256, type=int) +parser.add_argument('--save_loc', default='results/ICML', type=str, help='folder to save results') +parser.add_argument('--save_string', default='naswot', type=str, help='prefix of results file') +parser.add_argument('--score', default='hook_logdet', type=str, help='the score to evaluate') +parser.add_argument('--nasspace', default='nasbench201', type=str, help='the nas search space to use') +parser.add_argument('--batch_size', default=128, type=int) +parser.add_argument('--kernel', action='store_true') +parser.add_argument('--dropout', action='store_true') +parser.add_argument('--repeat', default=1, type=int, help='how often to repeat a single image with a batch') +parser.add_argument('--augtype', default='none', type=str, help='which perturbations to use') +parser.add_argument('--sigma', default=0.05, type=float, help='noise level if augtype is "gaussnoise"') parser.add_argument('--GPU', default='0', type=str) parser.add_argument('--seed', default=1, type=int) +parser.add_argument('--init', default='', type=str) parser.add_argument('--trainval', action='store_true') +parser.add_argument('--activations', action='store_true') +parser.add_argument('--cosine', action='store_true') parser.add_argument('--dataset', default='cifar10', type=str) parser.add_argument('--n_samples', default=100, type=int) parser.add_argument('--n_runs', default=500, type=int) +parser.add_argument('--stem_out_channels', default=16, type=int, help='output channels of stem convolution (nasbench101)') +parser.add_argument('--num_stacks', default=3, type=int, help='#stacks of modules (nasbench101)') +parser.add_argument('--num_modules_per_stack', default=3, type=int, help='#modules per stack (nasbench101)') +parser.add_argument('--num_labels', default=1, type=int, help='#classes (nasbench101)') args = parser.parse_args() os.environ['CUDA_VISIBLE_DEVICES'] = args.GPU -import torch -import torch.nn as nn -from torch.utils.data import DataLoader -import torchvision.datasets as datasets -import torch.optim as optim - -from models import get_cell_based_tiny_net - # Reproducibility torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False @@ -37,120 +51,140 @@ random.seed(args.seed) np.random.seed(args.seed) torch.manual_seed(args.seed) -import torchvision.transforms as transforms -from datasets import get_datasets -from config_utils import load_config -from nas_201_api import NASBench201API as API -def get_batch_jacobian(net, x, target, to, device, args=None): +def get_batch_jacobian(net, x, target, device, args=None): net.zero_grad() - x.requires_grad_(True) - - _, y = net(x) - + y, ints = net(x) y.backward(torch.ones_like(y)) jacob = x.grad.detach() - - return jacob, target.detach() - - -def eval_score(jacob, labels=None): - corrs = np.corrcoef(jacob) - v, _ = np.linalg.eig(corrs) - k = 1e-5 - return -np.sum(np.log(v + k) + 1./(v + k)) - + return jacob, target.detach(), y.detach(), ints.detach() device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") -print(device) -THE_START = time.time() -api = API(args.api_loc) - +searchspace = nasspace.get_search_space(args) +train_loader = datasets.get_data(args.dataset, args.data_loc, args.trainval, args.batch_size, args.augtype, args.repeat, args) os.makedirs(args.save_loc, exist_ok=True) -train_data, valid_data, xshape, class_num = get_datasets(args.dataset, args.data_loc, cutout=0) - -if args.dataset == 'cifar10': - acc_type = 'ori-test' - val_acc_type = 'x-valid' - -else: - acc_type = 'x-test' - val_acc_type = 'x-valid' - -if args.trainval: - cifar_split = load_config('config_utils/cifar-split.txt', None, None) - train_split, valid_split = cifar_split.train, cifar_split.valid - train_loader = torch.utils.data.DataLoader(train_data, batch_size=args.batch_size, - num_workers=0, pin_memory=True, sampler= torch.utils.data.sampler.SubsetRandomSampler(train_split)) - -else: - train_loader = torch.utils.data.DataLoader(train_data, batch_size=args.batch_size, shuffle=True, - num_workers=0, pin_memory=True) times = [] chosen = [] acc = [] val_acc = [] topscores = [] - -dset = args.dataset if not args.trainval else 'cifar10-valid' - order_fn = np.nanargmax + +if args.dataset == 'cifar10': + acc_type = 'ori-test' + val_acc_type = 'x-valid' +else: + acc_type = 'x-test' + val_acc_type = 'x-valid' + + + runs = trange(args.n_runs, desc='acc: ') for N in runs: start = time.time() - indices = np.random.randint(0,15625,args.n_samples) + indices = np.random.randint(0,len(searchspace),args.n_samples) scores = [] + npstate = np.random.get_state() + ranstate = random.getstate() + torchstate = torch.random.get_rng_state() for arch in indices: - - data_iterator = iter(train_loader) - x, target = next(data_iterator) - x, target = x.to(device), target.to(device) - - config = api.get_net_config(arch, args.dataset) - config['num_classes'] = 1 - - network = get_cell_based_tiny_net(config) # create the network from configuration - network = network.to(device) - - jacobs, labels= get_batch_jacobian(network, x, target, 1, device, args) - jacobs = jacobs.reshape(jacobs.size(0), -1).cpu().numpy() - try: - s = eval_score(jacobs, labels) + uid = searchspace[arch] + network = searchspace.get_network(uid) + network.to(device) + if args.dropout: + add_dropout(network, args.sigma) + if args.init != '': + init_network(network, args.init) + if 'hook_' in args.score: + network.K = np.zeros((args.batch_size, args.batch_size)) + def counting_forward_hook(module, inp, out): + try: + if not module.visited_backwards: + return + if isinstance(inp, tuple): + inp = inp[0] + inp = inp.view(inp.size(0), -1) + x = (inp > 0).float() + K = x @ x.t() + K2 = (1.-x) @ (1.-x.t()) + network.K = network.K + K.cpu().numpy() + K2.cpu().numpy() + except: + pass + + + def counting_backward_hook(module, inp, out): + module.visited_backwards = True + + + for name, module in network.named_modules(): + if 'ReLU' in str(type(module)): + #hooks[name] = module.register_forward_hook(counting_hook) + module.register_forward_hook(counting_forward_hook) + module.register_backward_hook(counting_backward_hook) + + random.setstate(ranstate) + np.random.set_state(npstate) + torch.set_rng_state(torchstate) + + data_iterator = iter(train_loader) + x, target = next(data_iterator) + x2 = torch.clone(x) + x2 = x2.to(device) + x, target = x.to(device), target.to(device) + jacobs, labels, y, out = get_batch_jacobian(network, x, target, device, args) + + if args.kernel: + s = get_score_func(args.score)(out, labels) + elif 'hook_' in args.score: + network(x2.to(device)) + s = get_score_func(args.score)(network.K, target) + elif args.repeat < args.batch_size: + s = get_score_func(args.score)(jacobs, labels, args.repeat) + else: + s = get_score_func(args.score)(jacobs, labels) + except Exception as e: print(e) - s = np.nan - + s = 0. + scores.append(s) + #print(len(scores)) + #print(scores) + #print(order_fn(scores)) + + + best_arch = indices[order_fn(scores)] - info = api.query_by_index(best_arch) + uid = searchspace[best_arch] topscores.append(scores[order_fn(scores)]) chosen.append(best_arch) - acc.append(info.get_metrics(dset, acc_type)['accuracy']) + #acc.append(searchspace.get_accuracy(uid, acc_type, args.trainval)) + acc.append(searchspace.get_final_accuracy(uid, acc_type, False)) if not args.dataset == 'cifar10' or args.trainval: - val_acc.append(info.get_metrics(dset, val_acc_type)['accuracy']) + val_acc.append(searchspace.get_final_accuracy(uid, val_acc_type, args.trainval)) + # val_acc.append(info.get_metrics(dset, val_acc_type)['accuracy']) times.append(time.time()-start) - runs.set_description(f"acc: {mean(acc if not args.trainval else val_acc):.2f}%") + runs.set_description(f"acc: {mean(acc):.2f}% time:{mean(times):.2f}") print(f"Final mean test accuracy: {np.mean(acc)}") -if len(val_acc) > 1: - print(f"Final mean validation accuracy: {np.mean(val_acc)}") +#if len(val_acc) > 1: +# print(f"Final mean validation accuracy: {np.mean(val_acc)}") state = {'accs': acc, - 'val_accs': val_acc, 'chosen': chosen, 'times': times, 'topscores': topscores, } -dset = args.dataset if not args.trainval else 'cifar10-valid' -fname = f"{args.save_loc}/{dset}_{args.n_runs}_{args.n_samples}_{args.seed}.t7" +dset = args.dataset if not (args.trainval and args.dataset == 'cifar10') else 'cifar10-valid' +fname = f"{args.save_loc}/{args.save_string}_{args.score}_{args.nasspace}_{dset}_{args.kernel}_{args.dropout}_{args.augtype}_{args.sigma}_{args.repeat}_{args.batch_size}_{args.n_runs}_{args.n_samples}_{args.seed}.t7" torch.save(state, fname) diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..800f42f --- /dev/null +++ b/utils.py @@ -0,0 +1,100 @@ +import torch +from pycls.models.nas.nas import Cell + +class DropChannel(torch.nn.Module): + def __init__(self, p, mod): + super(DropChannel, self).__init__() + self.mod = mod + self.p = p + def forward(self, s0, s1, droppath): + ret = self.mod(s0, s1, droppath) + return ret + + +class DropConnect(torch.nn.Module): + def __init__(self, p): + super(DropConnect, self).__init__() + self.p = p + def forward(self, inputs): + batch_size = inputs.shape[0] + dim1 = inputs.shape[2] + dim2 = inputs.shape[3] + channel_size = inputs.shape[1] + keep_prob = 1 - self.p + # generate binary_tensor mask according to probability (p for 0, 1-p for 1) + random_tensor = keep_prob + random_tensor += torch.rand([batch_size, channel_size, 1, 1], dtype=inputs.dtype, device=inputs.device) + binary_tensor = torch.floor(random_tensor) + output = inputs / keep_prob * binary_tensor + return output + +def add_dropout(network, p, prefix=''): + #p = 0.5 + for attr_str in dir(network): + target_attr = getattr(network, attr_str) + if isinstance(target_attr, torch.nn.Conv2d): + setattr(network, attr_str, torch.nn.Sequential(target_attr, DropConnect(p))) + elif isinstance(target_attr, Cell): + setattr(network, attr_str, DropChannel(p, target_attr)) + for n, ch in list(network.named_children()): + #print(f'{prefix}add_dropout {n}') + if isinstance(ch, torch.nn.Conv2d): + setattr(network, n, torch.nn.Sequential(ch, DropConnect(p))) + elif isinstance(ch, Cell): + setattr(network, n, DropChannel(p, ch)) + else: + add_dropout(ch, p, prefix + '\t') + + + + +def orth_init(m): + if isinstance(m, (torch.nn.Conv2d, torch.nn.Linear)): + torch.nn.init.orthogonal_(m.weight) + +def uni_init(m): + if isinstance(m, (torch.nn.Conv2d, torch.nn.Linear)): + torch.nn.init.uniform_(m.weight) + +def uni2_init(m): + if isinstance(m, (torch.nn.Conv2d, torch.nn.Linear)): + torch.nn.init.uniform_(m.weight, -1., 1.) + +def uni3_init(m): + if isinstance(m, (torch.nn.Conv2d, torch.nn.Linear)): + torch.nn.init.uniform_(m.weight, -.5, .5) + +def norm_init(m): + if isinstance(m, (torch.nn.Conv2d, torch.nn.Linear)): + torch.nn.init.norm_(m.weight) + +def eye_init(m): + if isinstance(m, torch.nn.Linear): + torch.nn.init.eye_(m.weight) + elif isinstance(m, torch.nn.Conv2d): + torch.nn.init.dirac_(m.weight) + + + +def fixup_init(m): + if isinstance(m, torch.nn.Conv2d): + torch.nn.init.zero_(m.weight) + elif isinstance(m, torch.nn.Linear): + torch.nn.init.zero_(m.weight) + torch.nn.init.zero_(m.bias) + + +def init_network(network, init): + if init == 'orthogonal': + network.apply(orth_init) + elif init == 'uniform': + print('uniform') + network.apply(uni_init) + elif init == 'uniform2': + network.apply(uni2_init) + elif init == 'uniform3': + network.apply(uni3_init) + elif init == 'normal': + network.apply(norm_init) + elif init == 'identity': + network.apply(eye_init) diff --git a/visualiser.py b/visualiser.py deleted file mode 100644 index c1edfe2..0000000 --- a/visualiser.py +++ /dev/null @@ -1,81 +0,0 @@ -import re -from graphviz import Digraph -import pandas as pd -import time -import argparse - -parser = argparse.ArgumentParser(description='Fast cell visualisation') -parser.add_argument('--arch', default=1, type=int) -parser.add_argument('--save', action='store_true') -args = parser.parse_args() - -def set_none(bit): - print(bit) - tmp = bit.split('~') - tmp[0] = 'none' - print('~'.join(tmp)) - return '~'.join(tmp) - -def remove_pointless_ops(archstr): - old = None - new = archstr - while old != new: - old = new - bits = old.strip('|').split('|') - if 'none~' in bits[0]: # node 1 has no connections to it - bits[3] = set_none(bits[3]) # node 1 -> 2 now none - bits[6] = set_none(bits[6]) # node 1 -> 3 now none - if 'none~' in bits[2] and 'none~' in bits[3]: # node 2 has no connections to it - bits[7] = set_none(bits[7]) # node 2 -> 3 now none - if 'none~' in bits[7]: # doesn't matter what comes through node 2 - bits[2] = set_none(bits[2]) # node 0 -> 2 now none - bits[3] = set_none(bits[3]) # node 1 -> 2 now none - if 'none~' in bits[6] and 'none~' in bits[7]: # doesn't matter what comes through node 1 - bits[0] = set_none(bits[0]) # node 0 -> 1 now none - new = '|'.join(bits) - print(new) - return new - - -df = pd.read_pickle('results/arch_score_acc.pd') - -nodestr = df.iloc[args.arch]['cellstr'] -nodestr = nodestr[1:-1] # remove leading and trailing bars | - -nodestr = remove_pointless_ops(nodestr) -nodes = nodestr.split("|+|") - -dot = Digraph( - format='pdf', - edge_attr=dict(fontsize='12'), - node_attr=dict(fixedsize='true',shape="circle", height='0.5', width='0.5'), - engine='dot') - -dot.body.extend(['rankdir=LR']) - -OPS = ['conv_3x3','avg_pool_3x3','skip_connect','conv_1x1','none'] - -dot.node('0', 'in') - -## ops are separated by bars (|) so -for i, node in enumerate(nodes): - - # if node 3 then label as output - if (i+1) == 3: - dot.node(str(i+1), 'out') - else: - dot.node(str(i+1)) - - for op_str in node.split('|'): - op_name = [o for o in OPS if o in op_str][0] - if op_name == 'none': - break - connect = re.findall('~[0-9]', op_str)[0] - connect = connect[1:] - dot.edge(connect,str(i+1), label=op_name) - -dot.render( view=True) - - -if args.save: - dot.render(f'outputs/{args.arch}.gv')