{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Distributed Machine Learning Model Sweeping" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are two use cases for training machine learning models in a distributed setting. The [dask-ml](https://ml.dask.org/) documentation does a good job of describing this. The first use case is more memory-bound problems. This is when the dataset has to be divided across multiple machines because it doesn't fit in a single one. A single model is then training on the distributed dataset.\n", "\n", "The second use case is for compute-bound problems. A data scientist has datasets that fit in memory, but they want to train multiple models and evaluate the performance in parallel. Extending this idea, big data often has logical groupings that can be used to partition the data. We can then train multiple models on each dataset.\n", "\n", "This tutorial will focus on the compute-bound problem. For example, if we have a large dataset that spans 5 regions, we can train region-specific models. For each region, we can train 5 different models, which models in 25 model training runs. These 25 model trainings can be distributed on a cluster and run in parallel as they are independent. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Training Multiple Models for One Dataset\n", "\n", "**Creating a Dataset**\n", "\n", "We start by creating a `make_data()` function using the sklearn `make_regression()` function. This function takes in a number of `groups` and for each group, generates a new dataset. This means that each group will have different properties when we generate multiple groups and benefit from separate models. For now though, we focus on the training logic for a single group." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "from sklearn.datasets import make_regression\n", "\n", "def make_data(groups=1):\n", " result = []\n", " for i in range(groups):\n", " X, y = make_regression(n_samples=100, n_features=8, n_informative=5, noise=10)\n", " df = pd.DataFrame({\"group\": [f\"group{i}\"]*100})\n", " df = pd.concat([df, pd.DataFrame(X, columns=[f\"x{n}\" for n in range(8)])], axis=1)\n", " df = df.assign(y=y)\n", " result.append(df)\n", " return pd.concat(result, axis=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using this with one group gives us a dataset with 8 features and a target variable called `y`. The head of the DataFrame is shown below." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
groupx0x1x2x3x4x5x6x7y
0group00.971978-0.473416-2.2210272.066071-0.371581-1.8065690.154867-2.329968-241.530733
1group0-1.1784253.071536-0.6822512.0394250.6955980.3401940.147516-0.891319-14.439953
2group00.128803-0.2041610.581653-0.7694400.7252070.192606-1.2508610.73240378.005286
3group0-1.3815501.3917470.7484210.1872810.6605801.665103-1.303355-1.86986731.560241
4group01.5753590.926507-1.364626-0.267989-1.179624-1.5895611.051079-0.507540-17.564240
\n", "
" ], "text/plain": [ " group x0 x1 x2 x3 x4 x5 \\\n", "0 group0 0.971978 -0.473416 -2.221027 2.066071 -0.371581 -1.806569 \n", "1 group0 -1.178425 3.071536 -0.682251 2.039425 0.695598 0.340194 \n", "2 group0 0.128803 -0.204161 0.581653 -0.769440 0.725207 0.192606 \n", "3 group0 -1.381550 1.391747 0.748421 0.187281 0.660580 1.665103 \n", "4 group0 1.575359 0.926507 -1.364626 -0.267989 -1.179624 -1.589561 \n", "\n", " x6 x7 y \n", "0 0.154867 -2.329968 -241.530733 \n", "1 0.147516 -0.891319 -14.439953 \n", "2 -1.250861 0.732403 78.005286 \n", "3 -1.303355 -1.869867 31.560241 \n", "4 1.051079 -0.507540 -17.564240 " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = make_data(1)\n", "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Training Setup**\n", "\n", "We import some relevant libraries for model training." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from sklearn.linear_model import LinearRegression\n", "from sklearn.svm import SVR\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import mean_absolute_error\n", "\n", "feature_cols = [f\"x{n}\" for n in range(8)]\n", "target = \"y\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Creating the training manifest**\n", "\n", "For this single dataset, we create a new dataframe with the `create_training_manifest()` function below that will be responsible for orchestrating our training runs. We call this a training manifest as each row holds the metadata for one training run. The manifest contains metadata, the `X` and `y` of our dataset along with the `model` to use for training. For now, this may look like more work for a single dataset, but later on we'll see how this can scale to Spark or Dask easily with this setup.\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "from typing import List, Dict, Any\n", "import pickle\n", "\n", "def create_training_manifest(df: pd.DataFrame, models: List[Any]) -> List[Dict[str,Any]]:\n", " group = df.iloc[0][\"group\"]\n", " X_cols = pickle.dumps(df[feature_cols])\n", " y_col = pickle.dumps(df[target])\n", " result = []\n", " for model in models:\n", " model_binary = pickle.dumps(model)\n", " model_name = type(model).__name__\n", " index = f\"{group}-{model_name}\"\n", " result.append({\"index\":index, \"group\": group, \"X\": X_cols, \"y\": y_col, \"model_name\": model_name,\"model\": model_binary})\n", " return result" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Why use pickle to serialize?**\n", "\n", "There are multiple reasons to use `pickle` to serialize our data and model. First is that distributed operations are passed through a network. Using the serialized version reduces the memory footprint of the data we pass through the network. The second reason is that it lets us have a `pd.DataFrame` inside a cell of our training manifest. Last, the serialized `binary` type is also an acceptable data format for Pandas, Spark, and Dask.\n", "\n", "We can test this function by simply invoking it." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'index': 'group0-LinearRegression',\n", " 'group': 'group0',\n", " 'X': b'\\x80\\x03cpandas.core.frame\\nDataFrame\\nq\\x00)\\x81q\\x01}q\\x02(X\\x04\\x00\\x00\\x00_mgrq\\x03cpandas.core.internals.managers\\nBlockManager\\nq\\x04cfunctools\\npartial\\nq\\x05cpandas.core.internals.blocks\\nnew_block\\nq\\x06\\x85q\\x07Rq\\x08(h\\x06)}q\\tX\\x04\\x00\\x00\\x00ndimq\\nK\\x02sNtq\\x0bbcnumpy.core.multiarray\\n_reconstruct\\nq\\x0ccnumpy\\nndarray\\nq\\rK\\x00\\x85q\\x0eC\\x01bq\\x0f\\x87q\\x10Rq\\x11(K\\x01K\\x08Kd\\x86q\\x12cnumpy\\ndtype\\nq\\x13X\\x02\\x00\\x00\\x00f8q\\x14\\x89\\x88\\x87q\\x15Rq\\x16(K\\x03X\\x01\\x00\\x00\\x00M\\xd6?\\xb1\\xf1\\x1d!\\x95)\\xff\\xbf`\\xfe\\xdbQ*{\\xd2\\xbf`\\x1bT`\\\\\\x93\\xec?^C\\x1bp\\xdc\\xba\\xb7?\\xfcmv\\xfa\\xb33\\xe7?r\\x82\\xce)\\x84*\\xf9?\\xd7\\x9f\\xdf:0\\xd6\\x01@\\x17s>\\xe1\\xebF\\xf4?9.^\\x9a\\x8b\\xb5\\xa6?\\xcc\\xcd\\x8a\\xb9Qa\\xbe\\xbf\\xdab\\x03\\x98\\xbdK\\xc1?l\\xc6\\xfa@6S\\xe9?\\x1b\\xe6\\xc5\\x9f\\x13*\\xe6?)\\x1aIl\\xdf\\x88\\xe0\\xbf\\xebg\\xe8\\x01\\x88\\x91\\xdf\\xbf\\xc6\\xe9\\xb3\\xe8\\x94\\xef\\xd7\\xbf\\xda\\x1c\\x17\\x90\\xf5\\xd3\\xa5\\xbf\\x91U\\x9e\\x9c\\'\\x86\\xf2\\xbfF\\xb8\\xea\\x8c\\x0f(\\xe3\\xbf}\\xdc\\x14\\xfdvk\\xf4?\\xffJ\\xe2c\\x19\\xc7\\xc1?\\xe2\\x95\\x86\\x0clZ\\xd5\\xbf+\\xb0\\xa7\\xc1\\xb4\\x98\\xa3?\\x94\\xf7\\xab\\x95J\\xa2\\xf3\\xbf\\xc4\\xef4\\x1e\\xb4\\xa8\\xef\\xbf\\xb4\\x03>\\x80\\xc9\\x04\\xf5?\\xbcm\\x8f\\xdc|;\\xdd\\xbf2\\x10\\xfc\\xe1DF\\x00@w\\xff\\x93\\xa4\\xea\\x08\\xa8?&[\\x9b\\xa8\\xd0\\xdb\\xc3?\\\\>\\xd9)\\xbdo\\xca?\\x87L\\x98\\xda\\xc2U\\xfe?I@\\xb5\\xfdr\\x17\\xce\\xbfB\\xf2t\\xb9\\x19\\xb1\\x9a?:\\xef\\x82,=e\\xe2\\xbf\\xfa\\xb7n\\xc7E\\x95\\xbc\\xbf[oc\\x94\\xd8\\x0b\\xf9\\xbf\\xe4?$\\x91z\\n\\xee?\\x17\\xbb\\rG\\xd6\\xbe\\xd3\\xbff\\xf0\\x03B;\\xda\\xee\\xbf\\x90\\xba\\x8d\\x8a\\x82\\xe5\\xd0\\xbf\\x93aE\\xa1.\\x83\\xe0\\xbfT\\xea\\xd3;\\xe5\\xd6\\xcf\\xde\\x9f\\xfb?\"#\\xc9\\xfa\\xce\\x16\\x1f\\xbf\\xee\\xd6B\\x87\\xea\\x11\\x00@R\\x85>\\xb0 \\x8c\\xf2?b\\x81\\xe6~\\x87\\x83\\xf6\\xbf\\xe3~5\\xed\\x96\\xe9\\xdf?\\x97&~\\x8cD\\xba\\xcb?W,\\x04V\\x13\\x08\\xf1?\\x9c}\\x1ff\\x9dv\\xcf\\xbf9\\x03\\x86G\\x03;\\xf0?\\xd4Nw\\xe1\"\\x8a\\xe3\\xbf\\xa9\\xbe\\x02\\x8b\\xde%\\xd7?\\xd6\\x8cOA\\xd0\\x95\\xd4\\xbf\\x00R\\xe9\\xbd\\xf3_\\xf8\\xbfZju\\xae\\xc5\\xea\\xf1?\\xb9\\xf2N\\xff\\xec\\x05\\xd1\\xbf\\x99\\xad\\x84;\\xcd\\xee\\xe3?\\xaeJ\\x9d\\\\\\x8d8\\xf6\\xbf\\xa7\\x9el\\xba\\x9d\\xb7\\xfe?\\xf2\\xe0@\\x88\\xfc\\x9e\\xd8?\\xa3jR\\x96\\xa9\\xc4\\x01\\xc0\\xbb\\xcc\\x12\\xf8\\xff\\xd4\\xe5\\xbf\\xca\\xf5R\\xcf\\xe6\\x9c\\xe2?\\x0b\\x7f?\\xbe\\x0f\\xf3\\xe7?9?\\xd2&\\x82\\xd5\\xf5\\xbf\\x82\\xcdd\\xca\\xd9t\\xca\\xbf\\x84PVz\\xe1N\\xec\\xbf\\x04\\xd3\\x9blv\\xf1\\t`\\xe0?\\xdc\\x80\\xb5\\xce\\xdb\\xfc\\xe4\\xbf\\xceG\\x1b\\xa7K\\xcb|?\\xf1\\xfa\\x9cB\\xec\\x90\\xea?\\x10\\xe0\\']\\xd2\\xf4\\xe0\\xbf\\xcd9\\xa2B\\xeb\\x8d\\xc7\\xbf\\xa0\\xac\\xeb\\xf2\\xfd#\\xf6?\\xe5\\xb1\\xe1\\t\\xb2\\x1f\\xdf\\xbfH$\\xb6\\x01C\\xbd\\xf6?z\\xdf\\x969\\xfc\\x1b\\xf5\\xbf\\xba^\\xd4h\\xc4\\xa2\\xe4?\\xf3,\\x1e\\x05-\\x0e\\xec?f\\x98\\xe6\\xc9S,\\xf0?%\\x92Eh\\xd3\\x1a\\xb4\\xbfHj\\x8d\\x1a\\xcd\\xcap\\xbf\\xdb\\x12C6\\xd8\\x15\\xee?p\\x86\\xc6\\xc0\\xe2H\\xda?\\x0bb=^\\xcf\\xe0\\xde?\\xd8]\\xa5\\xa9dP\\xf1\\xbf\\xd7f\\xf1\\xd9o\\xe4\\xd3?\\x132\\xfc\\xd1\\x90\\x14\\x03@\\xfb\\x15\\xaa\\x0f<\\xfa\\xd4\\xbf\\x8b\\xf3;\\xbeL\\xac\\xe5\\xbf\\xc7F\\\\/\\xd7\\x92\\xfb?;\\x05\\x06\\xd0s.\\xc3\\xbf\\xa0\\x8e:+\\x99\\xfb\\xd7?V\\x1fJ\\xecN\\xdb\\xa5\\xbf\\xc5+\\xd4\\xf4\\x924\\xe5\\xbfBi\\x8f\\xaa\\x12\\x15\\xdb\\xbffQ\\xd8\\xd1\\x7f\\xcd\\xcc?\\x90=J \\xf6\\n\\xd5?\\xdeq)+\\x9c\\xe5\\x02@._\\xb5\\x1b\\x15\\xc3\\xee?\\xd4\\x944\\x92\\x18<\\xe9\\xbf!\\x94\\xe8\\xeer\\xe7\\xf1?;n!\\x1aX8\\xc7\\xbfQ$\\xa8v\\x84\\xc6\\xe7?\\xc9\\x17\\x92\\xa7B\\x01\\xce?5eCM\\xee\\xad\\xf3?R\\xdeg\\x947\\xd7\\xe6?@\\xc2\\r\\xbb\\xf2J\\xe9?\\t\\xa9r\\x0e\\xd0\\xaa\\xd1\\xbf4\\x01\"\\xcb\\xf5\\x84\\xcd\\xbfm\\x1b\\xd0\\x11\\xd1\\xfd\\xf6\\xbf\\x10x\\x9c~ \\xab\\xed?e\\x9d\\t\\x84\\x8eI\\xeb\\xbf\\xad=\\xf0f\\x8f\\xfe\\x8c?\\xea\\x93\\x14}\"\\xa6\\xda\\xbf\\x98WU\\xb7}c\\xce\\xbf\\xcce\\xa2w_i\\xe1\\xbf)\\xef7L\\xa5\\x7f\\xf5\\xbf\\x93=\\x15k\\x83\\xf9\\xce\\xbfe9\\xbd\\xb6\\xabx\\xdc?\\xa4\\xcbE\\xab\\xc6\\xc0\\xbe?\\xd2\\xcbM\\x8c\\x1d\\x94\\xd3?\\x9ct\\xb0\\x16\\xe4A\\xf1\\xbf!d\\xd2\\x11sZ\\xf4\\xbf\\xe3\\x15P\\x0eq\\xf7\\xee\\xbf\\x1e- \\xab\\x93\\x96\\xc3?\\xae\\xe0\\xcf\\xbe\\xa68\\xd7\\xbf\\xa6\\xa9\\xa9\\xc3J\\x0f\\xaa\\xbf\\x17%+ZfJ\\xb7?\\x00\\xc6Z\\xf8\\x82u\\xf5?\\x94\\xf9#\\x0e\\x05\\xe2\\xe6?g\\x9a\\x0f\\xb5\\xbf\\xf0\\xea?h\\xd5O\\x92\\x11\\xa8\\xf5\\xbf\\x94u_\\xa3k\\xfa\\xf0?\\xeei\\xf2\\x85\\xb9h\\xdb?\\x13\\xe9r\\x1f\\x8dI\\xaa\\xbf\\xaf\\xbc\\x15\\x81\\x895\\xea\\xbf\\x82M\\xd6\\xb3M\\x0f\\xf4\\xbf\\xb2n\\xe2\\x1c\\x96\\xf9\\xe0\\xbf<\\xecT\\xe8\\xf9\\xcf\\xda\\xbf\\x04$\\xb3a\\x94\\xbe\\xf6\\xbf\\xa3\\x85\\xfcH\\xe2\\xad\\xfc\\xbf\\xb7\\xb1:\\xd0\\x16j\\xf1?\\xa4\\xf3\\xa7\\x90\\x92J\\xf4?VqR\\x06\\x9e\\xcc\\xee\\xbfCW\\xc0XN\\xb5\\xd3?\\xfd\\xb4\\xb4s_\\x8f\\xf8?\\n\\x0e\\xa0\\xf7\\xeay\\xfe?\\x9f\\x94JZ\\xc8a\\xe1\\xbf\\xc8\\x8bC\\xea[r\\x02@\\xfa\\xcc\\x03%\\xef\\xe6\\xf3\\xbf^\\xe5\\xdc\\x874i\\xd3\\xbfj4\\x19;P\\x87\\x00@i\\xd6\\xb7+\\xbeP\\x00@\\xd1\\x91\\xc0\\xf9?\\x9f\\xe8\\xbf\\x12\\x02\\x81\\xfb\\xcf\\xf8\\xc7?)a\\xf1\\x9c\\xb9&\\xd1\\xbf\\xd4\\xdf@\\xb2\\xee\\xb7\\x00@=\\x9c\\xe9/\\xf8m\\xe2\\xbf\\x0b0\\xea\\\\a`\\xe9\\xbf\\x1a\\x86\\x85D,\\xeb\\xf1\\xbf\\xb4)\\xe6\\x08\\'\\xb8\\xd9?\\x8a\\xb0EN\\xcb\\x99\\xf2\\xbfr\\xf80\\x93\\x10\\x99\\x03@\\x08\\x83\\xd66&\\xaf\\xdf\\xbf$\\n!\\xdc\\xaaz\\xd8\\xbf\\x17\\xd6\\x04\\t\\xa3\\xb0\\x89\\xbfPY\\x85\\xc8c=\\xac?r\\xff\\xec5U\\n\\xdd?i\\x03\\xd5t#\\xcd\\xf3?\\xf4kc\\x04\\xe5\\xc4\\xe5\\xbf\\x98\\xb1\\xbf=\\x0b\\r\\xd8\\xbf\\xef\\x11\\xc2\\xf7\\xe7\\xd2\\xf3?\\xe92SQ\\x15`\\xe6?6\\xe6\\x8aY\\xe7\\xc6\\xe5\\xbf\\x97\\xce|\\xc2R\\xd5\\xe2\\xbf\\xca\\x87\\xe5\\n\\xb5\\xc2\\xb0?1gA\\x0e\\xc4(\\xe5?\"8\\x02io\\xbe\\xe6\\xbf\\xae56\\xa3-\\xcf\\xdf\\xbf\\x9a\\xb5Vr\\xa1 \\xe0\\xbf\\xce\\x9c\\xee\\x1aVB\\xe9?\\xc0Ub\\xca\\x99\\xd6\\xc2\\xbf\\xa8\\xe7\\xfa96\\x03\\xe3?h)\\xfa\\x0cQru\\xbf\\xe0\\x8f\\x89\\x9d\\x11T\\xca?\\xad\\xb5\\x99mo\\x8b\\xfd\\xbf\\t g0\\x85\\xb1\\xe4\\xbf:6\\xf5\\xe0\\xba\\x16\\xe5\\xbfP\\x1fk\\xb7\\xa5\\xee\\xe4?v#=\\xd2\\x10\\r\\xe3\\xbf\\xd0ExU\\x86\\xfd\\xf7?\\xa5G\\x7fH\\xa3\\xd1\\xc3?\\n\\x85\\x88o\\xe1\\xa0\\xcf?\\xeb\\xa8uJO\\xf0\\x01@\\xc2\\x1c\\xb8\\x84\\xcf\\xd5\\xfc\\xbfS\\x99t\\xf51T\\xfd?\\x9e\\xa5\\xea\\xde\\xacP\\xc2\\xbf\\x1f!Oy\\xe1\\xf0\\xdd\\xbf\\xb7\\xf7\\xea\\x0c\\x8b\\xba\\xe2?9r\\x0e\\xc2\\xa3O\\xdb\\xbf\\x13\\x80\\xa5\\x1ek-\\xd3?h\\xf9\\xe7P!\\r\\x01\\xc0\\n&K&#s\\xf1?\\xa2;\\xe3\\xc9e\\x86\\xb4?\\x95e3\\xdf\\x84\\xbe\\xd5?\\x16Q;\\xdf\\xa5\\xa8\\xe2?!GO|\\x8bh\\xfb\\xbfg\\xc3\\x11\\xc4\\xfaT\\xd7?t\\xd4\\xc2M\\x90?\\xe2?\\xce\\xd5\\x07\\tu\\xf3\\xf1\\xbf\\xc6\\xb9\\r\\x9b\\xfd\\x15\\xf7\\xbfz\\xa0O|7l\\xf0\\xbf=\\x1b\\xf1\\xef4\\xc5\\xed\\xbf\\xc7\\x9a6,\\xa5\\x0c\\xe3?\\xa6\\x05w\\x98\\xf5\\xb9\\xdd\\xbfOb\\xfb\\xd0\\xc3\\xd4\\xf9?\\xfa\\xdc\\xdc\\xae\\x11\\x87\\xe3?\\xa4\\xd0v\\x8f\\x99:\\xf3\\xbf\\xf9nBs\\x8f]\\xe6\\xbf\\xd5{\\'C\\xdb+\\xf8?KO\\xf4D@\\xa7\\xd4\\xbf\\xaa\\x9aM\\x17\\xc2{\\xf9?\\xed3\\xcf\\xce1\\x1c\\xf1\\xbf\\x97\\xd7g\\xf3\\x00\\xfd\\xd5\\xbf\\xb6\\xc93\\x98R\\xad\\xf6?\\xd8\\xdcG\\x15\\xda\\xfb\\xea?\\x19\\xbcM5h\\x01\\xf5\\xbf\\x91\\x0b\\x83\\nQ1\\xc4\\xbf\\x0f\\xe5\\xb3\\xc3\\x9c\\x03\\xed\\xbfF\\xa9y%&l\\x9c\\xbfK$\\x1fZ\\xf9\\xd7\\xe9?\\x06\\x7f\\xba3\\x94t\\xfa\\xbf(\\xec\\x88\\x85\\xa7\\x88\\xfa\\xbf4\\xd5Q]~F\\xd4?C!\\xa8\\xd9\\x0c%\\xe1?\\xe0\\xcb\\xcf^\\x0c\\xc7\\xf1?d\\x9dJ\\x9fYF\\xf4\\xbfm\\xc8\\x0f\\xb6t\\xb9\\xf2?\\x8fu.\\x02C^\\xcc\\xbfB`\\xd8\\xf9L\\x98\\xea?\\xf7(3\\xefm<\\xcc\\xbf\\x8c\\xfa\\xe8\\x9aC\\x1a\\xf2?hj\\xfc\\r:}\\xd7?\\xa9a\\xb6\\x98\\xda\\x0e\\xe8?\\x82\\xb8J\\xfe\\x11\\xd3\\xe2?y\\xd3q\\x7f\\xc6\\x08\\xe8\\xbf[\\r\\xb8\\xce\\x0f\\xd5\\x93\\xbf\\x84U\\xf3\\xf7\\xd6?\\xe9\\x8a\\x80\\xc17\\xc8\\xc8\\xbf\\xffM\\xf1f\\x1b(\\xeb?\\xbb\\x05h\\xe1F\\xd5\\xf7?#\\x97\\'\\x99\\x0c\\xf5\\xe4?\\xfa\\xea\\xc4\\xbc\\x1c7\\xfc\\xbfp\\xc4\\xb3\\x05B\\x81\\xbc?\\xea\\xd7rj\\xb3&\\xda?\\xcd\\xc2Ox\\xe6\\xb3\\xd1\\xbfK\\xfd\\xd3-\\xf7\\xf0\\xe4?\\xd1\\xf1\\xb3\\xd8\\xd8\\xfe\\xda\\xbf\\x9b}i\\xd5,\\xb7\\xfd?*\\x84\\xa5z\\xfc\\xa6\\xd3\\xbf\\xa9x\\n\\x9e\\xd1\\xe3\\xf2?\\xdejAd\\xf3|\\xb6\\xbfI\\x93nOK\\xc7\\xe2?\\xb0\\x04\\xe2D\\xa0\\x80\\xb9\\xbfd\\x0c\\xab\\xd8\\xda\\x98\\xf6\\xbfw\\x8a\\x87\\xf2\\x06\\xa4\\xdb\\xbf\\xe2\\x0f\\xfc\\xf5\\t\\xc5\\xe4?\\x1ezx@9\\xbc\\xfa\\xbf\\xc67\\xec\\xd24 \\xea?\\xd2\\xc5C\\xb3c\\x01\\xea?F\\xf4\\xbe-\\xad\\x83\\xfb?\\xad\\x00\\x04\\xc7\\x98t\\xb3\\xbfz3\\x8e\\x87\\x85\\xf9\\xde\\xbf\\n\\xee8\\xae\\xff\\x1c\\xee\\xbf\\xe3\\x84k\\x1fSb\\xd2\\xbf\\x12\\xa5\\xc2_\\xa5\\xcf\\xd9?\\x14F\\x92\\x19\\x96\\xe0\\xe2?\\xd9\\x81$\\xf3\\xbd\\xb4\\xf4\\xbfJ\\xfda\\xab\\xe3{\\xda\\xbf!GM8\\xdf\\xa4\\xfb?\\xb8/9\\xe0&\\x95\\xe2?\\xc5\\xe9\"\\xf7\\xfa\\xb7\\x08\\xc0N\\xff;\\xcdc\\x0b\\xef\\xbfS&js\\xedX\\xcf?\\xe1yq\\xfaO\\x80\\xee\\xbfg\\x89-\\t\\xf8=\\xe1\\xbf\\x85\\x1e;\\xcb\\xa1\\x11\\xf7?G0\\xf3\\r\\x03\\x93\\xfb?\\xe68\\xac\\xb5\\xda\\xee\\xf9?F\\x9c\\xa2\\xb3M\"\\xe0\\xbfb\\x8ev_\\xebR\\xf8\\xbf\\xf8i\\x1fR\\x99\\xe9\\xfb?\\x88\\xdf\\xd3\\x19\\x14\\x14\\xa7?\\x82W\\xe9\\x96\\xb4(\\x03@\\x89\\xc3\\x07\\x9b\\xad\\xd9\\xcb\\xbfA:\\x1e\\xb3\\xcb\\x93\\xeb\\xbf\\xb4\\x87\\xf8i\\xbf\\xf9\\xb5\\xbf\\xf6\\xe9\\xa2\\xebP\\xa0\\xa0?N,3T\\x1f-\\xfd?a`mL\\x03\\x14\\xf7\\xbf\\xff\\xd8\\xf0\\xbe\\xa2\\xed\\xe7\\xbfX\\x8b\\xcf?\\xb6\\xb7\\xf6?\\xd9\\xf3\\xd3\\xf1\\xdfF\\xf6?\\x18s\\xdc\\xdf\\xe1\\xf9\\xd2?\\xdbSb8\\x7f=\\xe4\\xbf\\xff\\xa5b\\x04\\x91<\\xeb\\xbfl*\\xee\\xe4\\xa2\\x15\\xd2\\xbf%(\\n\\xf1\\x916\\xbd?UH\\xfc\\x95\\x85,\\xf1?\\x05Y\\x8dV\\xcf\\xe2\\xf2?\\xb5z\\x10\\xf8\\xe8/\\xf4?-\\xd2\\xd8\\n\\x84\\x9d\\xe1\\xbfd\\x05V\\xd2c\\xe4\\xf9?U\\x9f\\x92/M\\x18\\xf5?\\x15Y\\xf2\\xb0\\xc1\\xcc\\xfb\\xbf\\x8fq-\\xc9e\\xf7\\x04@\\x8b\\t\\xb0f\\x89Y\\xe4?\\xecV\\x06\\xb6\\xd1\\xbf\\xa3?R\\xd8\\x02\\xcf\\xd2h\\xec?\\x02q\\x84t\\x0c8\\xfa?\\xaf,\\x1b\\x9a^\\x14\\xef\\xbf\\xd8\\r\\xa5\\xed\\x19\\x86\\xda?4e\\xb7\\x90\\xf5\\xaa\\xe1?\\xf1\\xd0\\xc0\\x10\\xb5\\xe7\\xfc\\xbf\"\\xd9Z\\x19\\xbc\\xc5\\xd5?\\xf9\\xba\\x7f\\xb7L\\xa7\\xc8?\\xb8\\x00w\\xe1B\\xa4\\xfa?W\\x8f;\\x8c\\xd7n\\xf9\\xbf< _R\\x158\\xe4\\xbf\\t\\x11\\xff\\xf8,q\\xdb\\xbf#\\xd3\\xb6q\\xf3f\\xd7\\xbf\\tF\\x99$\\xf0\\x14\\xf8\\xbf5V\\x18u\\xb7<\\xd3\\xbfY\\xe6$\\x1b\\xdd|\\xd6?\\x1cT\\xb9\\xe8\\xcc\\x82\\xe5\\xbf\\x86c\\xaa9^,\\xec?\\x82\\xc7\\x16U\\x08s\\xf7\\xbf\\xd1i\\xcf\\x08\\xa0\\x02\\xe6?j\\x0c\\xcd\\x93\\x17E\\xb7\\xbfn\\xdbl\\x1b\\xeb\\xd8\\xf8\\xbf\\xeb\\x82p\\xbf6\\xfe\\xe6?\\xb7\\x05+w\\x01\\xca\\xf8?S\\x8b\\xcc\\xea\\xa8z\\xe0\\xbf\\r\\xe7:\\xb8\\xb6\\xae\\xe7?\\x18\\xc1\\x0b\\xecy(\\xfd\\xbfGG\\x94:\\xba\\xb5\\xea\\xbfBJL\\xc9\\x84>\\xdf?q\\x11\\xb5\\xd8\\xce\\x12\\xe5\\xbf\\xa3\\xae\\x0c#x?\\n\\xc0\\xf5\\xef\\xa7_ys\\xdb?)\\xe7\\xd2\\xd7d\\x9a\\xfb?\\xea\\x855\\xe0\\xa9s\\xe6?.\\xec\\xec\\xdd\\xe53\\xcd?&\\x86\\xb8\\xef\\xefE\\xf6?\\x08\\x83_(w\\x88\\xf9?\\x15\\xdagL\\x0ej\\xd2\\xbf,\\xd1O\\xee\\xdf\\x03\\xea\\xbf\\x8d\\xe2\\xcd`\\x10W\\xe8?\\x8d\\x97\\xed\\x94+\\x18\\xf2?\\x81\\x8aN\\x1cN\\x85\\xf1?\\xa6f\\xa6\\xed\\x14m\\xcd?\\xf4\\xb8\\x80\\xa7e{\\xf8\\xbf<2\\xc2>\\xac\\xb2\\xd8\\xbfE\\xc7U\\xae\\xce\\xf1\\xfd?\\xbe\\xd9\\x14\\'T\\x93\\xdd?8\\xd4,\\x87\\x98o\\x8a\\xbf\\x02\\xfb\\x14\\'`;\\xe3?\\xa6\\xfb\\x03;\\xbei\\x88\\xbf\\xf3\\xfe\\xbe\\xedp\\x12\\xfd?\\xd5\\x87\\xc4$c(\\xde?\\xb6\\xd8\\xabb\\x8e\\x0f\\xa3\\xbf\\xca\\xdc\\x9b\\xa0\\xf9\\xd8\\xf7?\\xb0\\xcd>\\x17=q\\xe7?(\\x9aAL:\\x14\\xc7\\xbf\\x8c\\xae\\xdbH\\x94\\x94\\xe1\\xbf\\xe7\\xc7\\xc5W\\xa1\\xa9\\xe3\\xbf^T\\x82\\x9arV\\xcd\\xbf\\xab\\xbdE\\xd9\\xaa0\\xef?>\\xd1\\xeeNp\\xdf\\xe1\\xbf\\xad\\xc7\\xeb{\\x08\\xa8\\xe4?\\xa7r\\xe0\\xa8\\xa2\\x93\\xe2\\xbf7y\\xe7,\\x15H\\xd9?25|\\\\\\xda\\xe2\\xf3\\xbf)\\x9f\\x16>\\x8e\\x04\\xf8\\xbf`U\\xfe\\x005\\xd4\\xef\\xbf~\\x01CQ\\x07\\xbe\\xd4\\xbf\\x11\\xb5\\xd8\\xed\\x06\\x94\\xea?j\\xe6\\xa2r-\\xa7\\xfe\\xbf\\x0e\\x15~\\xcc\\x97\\x19\\xed?\\x11\\xe45!\\x14\\xbd\\xcc?>706M4\\xf4\\xbf\\x16\\x1d\\xc6u\\xb9\\x1f\\xe1?<\\x17\\xcb\\x94\\xd9\\x9d\\x03@\\x04\\x18\\xd6\\x1f\\xec\\xff\\xaa?C6[\\x1fc\\xc5\\xb2?Z\\xef\\xcd\\xd4\\xd5N\\xf1\\xbfR\\xd7\\x04J\\xda\\x0e\\xe2?\\x80]x\\xc1\\x01e\\xdb?\\xff\\xf7\\xf3\\xb4\\x11Y\\xee\\xbf\\xd2\\tH\\xc1\\xb8\\x8f\\xde?\\x98\\x8e\\x05\\x8e\\x1b\\x96\\xec\\xbf?\\x14\\xb9\\x95\\xe8-\\xee?\\x19\\x92C\\x97a\\xc3\\xc6?\\x91\\xe9.4f\\xc3x\\xbf\\xf0!8\\x95\\xc9\\xdf\\xca\\xbf\\xdf\\xe7iQtF\\x9f?\\x17\\xb7\\x91\\xd6\\xe5?\\xe4\\xbf\\x07 2\\xce\\xc0_\\xed?|\\x99\\x16\\x14\\xda\\xc5\\xf2?IoVi\\x1d6\\x02\\xc0\\xcfbq\\xc0\\x94\\xcf\\xec?.H\\xde\\x12\\x89\\x1a\\xf1\\xbf\\x81\\x9a\\x940\\xf9\\x07\\xf3?0\\xfc\\x8dzlW\\xe0\\xbf\\x89\\x95\\x17\\x84\\x1b\\xd7\\xa5?\\xdaq\\xdax<\\xac\\xec?D\\xb7\\x13>\\xd0\\x97\\xf1?\\xde\\x06\\xf9\\xb4\\xb9\\x96\\xf7?\\xf3\\xfd\\xe6kt<\\xe7\\xbf\\x95\\xcbn\\xb1\\xff\\xbd\\xe4?JI\\xd4\\x18\\x97\\r\\x00@\\xfa\\xbc\\xaa\\xad/\\x97\\xfa\\xbf-\\r%\\xc7\\x1c\\x1c\\xd5?\\xddq\\xbe\\xf9\\xae\\xd2\\xc3?\\x05E5h\\xcd\\xe1\\xc2?\\xc9\\xef\\x82B\\x87\\x03\\xf4\\xbf\\xa7\\xf3}\\xa7\\x8a\\xda\\xf4\\xbf\\x1b\\x96\\x1c\\xc07\\xd1\\xf0?)\\xa1\\xa0u\\x87\\xf0\\xe1?\\x8b}\\x90\\xe1\\x10s\\xed?\\xae-;\\xfbu:\\xd9\\xbfI5\\xd91w\\xc8\\xdd?T\\xf0m\\n\\xadi\\xf4?J\\x0b\\x02_\\x81M\\xd7?\\xd6\\xa2F\\x9b\\x9c\\x9b\\xc3\\xbf\\xfdq)I\\xa2\\x05\\xe1?U8\\x14\\xdc\\xee\\xf3\\xdc\\xbfy\\x12\\x08\\x92\\xf5\\xda\\xed?V\\x04N#\\xbc\\x82\\xf7?\\xe4\\x07\\xc4r\\x88\\x1a\\xc0\\xbf\\xe5o!6f\\x92\\xf2?\\xc0\\xbc\\x1b\\xef\\x80\\xac\\xe1\\xbfA\\xfeR\\xd3v\\xa3\\xb8\\xbf\\xb2\\xd6\\x83\\xa6\\xcas\\xe6\\xbf\\xcc\\x0e4f\\xe8\\x1d\\xf4\\xbf\\xbc@gb\\xbf\\xa9\\xfb\\xbf\\xf5\\x00\\xf6a\\x91\\xd4\\xf6?\\x88\\x90\\x91\\xb8-\\'\\x02\\xc0\\xa5A\\x12\\xb8\\xd9\\x0b\\xe8\\xbf10\\x89\\xd4\\x0bz\\x04\\xc0\\xee5S\\xdc\\x83Z\\xe0?\\t=H\\x90\\xea\\x8d\\xda\\xbf.\\x8b\\x07\\x8d\\ri\\xf9\\xbf\\xba\\x01\\xa5\\xd3\\xc0\\\\\\xd1?\\x13\\xa8L\\x9b\\xc9\\xa3\\x01@nzG^\\x16\\xac\\xe5\\xbf\\x9b\\\\L\\x05\\xde\\xd3\\xdd? \\xc5\\xb2\\x08;\\xc8\\xce\\xbf\\xc0e:mx\\xa7\\xf5?\\x1ch\\xc8k\\xa7P\\xe9\\xbf=\\x86\\xd5o\\xfe\\x00\\xd2\\xbf\\x19\\x8b\\xd3\\xd4[\\xb9\\xbe\\xbf\\x9c\\x19\\xea0=\\xba\\xdd\\xbf.1K\\x87\\x00>\\xe7?@\\xc6\\xa1\\xbf]R\\xcf?}\\xa5\\x0f\\xeb\\x83{\\xa0\\xbfQ\\xc6\\xd7\\x1d2\\x8e\\xe3\\xbf\\xc7+\\xe1\\x80bu\\xcd?\\x97H\\n\\x11\\x7f\\xda\\xd6?\\xa4M 8\\xb0\\r\\xe2?\\xbb\\xcb\\xb2WK\\x87\\xeb\\xbf\\xf6\\x8e\\xbe\\xd7\\x07T\\xe6\\xbf\\xe8\\xc6\\xe8@\\xbf\\x8d\\xf9\\xbf\\xb6%\\x98O#\\xd2\\xf3\\xbf$6y\\xd5P!\\xc1?\\xf4\\xe5k\\x17\\xefw\\xf1\\xbfqU\\xa7\\xa5\\xd4\\xa7\\xd6?J\\xba}\\x16\\xfcw\\xd6\\xbf\\x1a&\\xb3\\x02\\xe8\\xa1\\xd6\\xbfP\\xc2\\xf0\\xc9\\x8e\\xd3\\xea\\xbf\\xa4Y\\xd3v\\x9b\\xf3\\xc9\\xbf\\xbd!\\x94\\xc1a\\x1f\\xef\\xbf\\xb4L\\x82\\xad\\x80.\\xfb?\\x91s\\xe3\\x06\\xea\\xac\\xf0\\xbf\\xb4\\xfd]\\xe3\\x13&\\xc1?U\\xa3\\x96\\xc7\\xd9\\x02\\xe2\\xbf\\xfd\\x04\\x03i\\x02\\xbd\\xc9\\xbf\\xee\\xb6\\xf3mF\\x1c\\xd9?\\xf0o\\x1cn \\xd0\\xe8?\\xb9\\n\\xc0}\\xbc!\\xda\\xbf\\xe0\\x06Y\\xd1\\xcd`\\xf6\\xbf\\x1e{q\\xa3\\xe0r\\xe2?\\xc3 W\\xe7\\x88Q\\xf5?\\xc5O\\xaf\\x89\\xf9\\xe0\\xde?P\\x89\\xf9|\\xda7\\x01@\\xed\\xce\\xac\\x04\\xeb\\xb7\\xdc\\xbf\\x0e\\x1f\\x1fSd\\x85\\xd1?p\\xff\\xd6D\\x91_\\xe2\\xbfmQu\\xaf\\x134\\xba\\xbf\\xa9B,`W\\\\\\xe3\\xbf\\x0f\\xb0!\\xfc\\xf1o\\xf1?\\xcf\\xe7{\\xbbak\\xd2\\xbfTf\\xf8\\x83\\t\\xce\\xeb?\\xdf\\x9a\"\\xc6\\xb0o\\xe1\\xbfT\\xb7a\\xf0p\\x8a\\xe9\\xbf\"\\x03\\xd5\\x1e\\xaa\\x1d\\xf1?\\x03w\\xccd\\x19\\xfd\\xf1\\xbf\\xdd\\xfcfS\\xbb\\xbf\\xe9?eP\\x190\\x8d.\\xb4?X\\x01d\\x92\\xc9\\xba\\xf4?Dw\\x02\\xc89\\xea\\xf2\\xbfB\\x81)>\\x12\\x16\\xf1?n\\xc9\\xadKF\\xc1\\xe7\\xbf\\x84\\xbb8Y-\\x90\\xeb?j\\xb6\\xf3A\\xe6\\x95\\xcf?p\\xe5\\x9e+KV\\xe3?\\xee\\xc1-\\xe5I)\\xe9\\xbf\\x18\\x8b\\x91\\xc9\\x89\\xcc\\xeb\\xbfA\\xbf\\xb6}\\xe4\\x00\\xeb\\xbf4\\xbb(\\xe6\\x01\\xd0\\xe6?\\xfe\\n\\xf5Z\\x9c\\xf3\\xd0?;\\xf0A\\xe8\\x92\\xe0\\xf4?\\xdf;\\x95i\\xad\\x15\\xc6\\xbf\\xcaZ\\x0c\\n\\xc6\\xa3\\x02\\xc0$\\x06\\xbam\\xb0\\x85\\xec\\xbf\\x13=)U\\xd9o\\xe7?\\xcd\\xd1\\xd1w\\xf9\\xea\\xfd\\xbf\\xf4\\xc4\\x8b,\\xc5=\\xe0\\xbf\\xdf\\xec\\xb7\\xa5\\xd3\\xd1\\xf2\\xbf\\xe4\\xb09P \\xf4\\xe1?S\\xa6\\xd9\\xcdl\\x87\\xbe?\\xa5\\x8cE\\x11(\\x8f\\xfa\\xbf.GkY\\xcd\\xac\\xf7\\xbfbS\\xef\\xbb,z\\xea\\xbf\\x1f\\x82S\\xd9\\x900\\xc1\\xbf\\xd8v/\\xb4\\xb0\\xad\\xc1\\xbf\\xe3\\x02\\xa6\\x9b\\t\\x08\\xc5\\xbf2~\\x8d\\xbe=\\xe4\\xe2?uf\\x8f\\xfb:\\x89\\xff?\\x1f\\xee\\x192\\x84\\x9d\\xce\\xbf@r\\n\\x96\\x16\\xf6\\xad?\\xb8\\x9a\\t\\xff\\xea\\x87\\xd2?q\\r\\xee$\\xe7\\x85\\xe3?\\xb0\\xee\\x19j}\\x18\\xf7?\\xf6{\\xbdlt\\xff\\xd1\\xbf\\x06Y\\xd8\\xf5\\x17\\xa7\\xf3\\xbf>\\tl\\xec\\xc6>\\xde\\xbf\\xd8.\\x85v\\x7f\\xd7\\xf3\\xbf\\xb3\\xc4\\x1c\\x12\\xab\\xbe\\xe9\\xbf\\xc2M\\x8b\\xbe\\xb0\\xd6\\xd3?\\xca=\\xea\\x13\\xd0F\\xe7?\\x1e\\x89\\x8f\\xe2P\\x17\\xb7?j\\xc2\\n\\xa9\\x10$\\xd6\\xbfr\\x1b2\\xee\\xe7\\xbf\\xf4\\xbf\\xe5k\\r\\x9c}u\\xdd\\xbf\\x83\\xcdz\\xe6\\x9d\\x88\\xd9\\xbf\\xab\\xea\\xf78#\\xc2\\xf1?\\xfb\\x9b\\xcc\\xf3*&\\xce?\\xc3\\x08z\\x95k\\x85\\xb3?\\xe2F\\x14\\xb0\\x8e\\xd6\\xe4?\\xfe\\xa2\\xb3\\xc4\\xea*\\xde?\\xd9\\xfc\\xbf\\x86\\xc0\\xbe\\xd1?\\xec\\xa8\\xdc\\x91Q\\xa4\\xe2?\\x8dWR/n;\\xea\\xbf${\\xac\\x8e\\x8e\\x7f\\xdc\\xbf\\xee\\x87\\tC6\\xae\\xdf?j\\xfd\\xec+7\\xad\\xd0?3_\\xda\\xc0]\\x07\\xf5?\\x081\\x1f\\x83\\xe5\\xff\\xeb\\xbfS\\xe9j\\x96B\\x86\\xd5?\\xab\\r\\xd9\\xadj\\xcf\\xec?\\xe7\\xbdE\\xaf*9\\xf6?\\xce$g\\xcc\\xb5\\xb1\\xcd\\xbf\\xc6R\\xd0\\xb3\\xd1,\\xf2?=;\\x10\\xe3\\x92\\xe3\\xf8\\xbf\\xbc\\x81\\xd3x~\\x12\\xf0\\xbf&\\xfd\\xc0\\xcbr\\x15\\xd9?\\xd8\\x15\\x9c\\x9adv\\xee?\\xb5\\xd3{#\\x1a\\x8a\\xe6\\xbf\\xa0\\x9e\\x1e\\x88\\xeb\\xf4\\xb8?\\xb3g\\x1d\\xf4\\xa4\\x89\\xd8?\\xeb\\xddz\\xf0h\\xcc\\xc7?\\xfa8\\x8b\\xf8(\\xca\\x00@\\xd6\\x1fe]\\xc4\\xe3\\xd1?\\x0brOf\\xbe\\xf5\\xca?\\xe7&\\xfa\\x9c\\xd6S\\xe0?\\n V&O\\xed\\xc3?\\xd8\\x19\\x1b\\x98\\xf2\\xeb\\xef?\\x8a3\\xaf\\xd5\\xd7\\x1c\\xa1?\\x03\\xb3v\\xfb_\\xb3\\xf0?\\x8c\\xbe\\xd8\\x884\\x97\\xf0?h~v\\x97\\xbd\\x8d\\xc3\\xbf\\xbbT\\xaaZ\\x10\\x1e\\xe3?\\x1c\"\\xadU|\\xa6\\xe1?\\xda\\x962\\x9a\\xc6;\\xf7\\xbf\\xef\\xc4+ \\xc5e\\xc7\\xbf[\\xcf5F\\xfa\\x83\\xb5\\xbf\\x129zk\\x87k\\xc2?E\\x96]n\\t \\xe2?1\\x02\\x8d\\xa7\\xb67\\xd6?K\\xfa-\\xed\\x99g\\xfc?\\xccZ!A\\xb6\\x03\\xca\\xbf\\xb2tV\\xc5D\\xfc\\xdf\\xbf\\xbc\\x00\\x1f\\x9dp\\xcb\\xf3?\\xeb\\xfb\\xec\\xa7\\'c\\x01\\xc0:Y*\\xc3\\xb58\\xd3?fD\\xa6w\\x1f\\xac\\xff\\xbf\\r\\xde\\x02\\x11Y\\xff\\xec?\\x90w\\x80\\x91s\\x9b\\xfe\\xbf\\x0e\\x82\\xef\\x18=\\x92\\xe1\\xbfd4\\xb8\\xb3\\xb7\\xf6\\xac\\xbf\\xe6Td\\xb1\\xb1\\xb8\\xda?\\xa5\\x8fn\\xc4\\xa2\\x80\\xe9?%\\x05\\x86\\xc4\\x93\\xfb\\xde?GP\\xba7\\xde\\xab\\xfe?E?\\xd0Fz\\xb0\\xb8?~\\xb0M\\xb1tE\\xe1?P\\xde\\xf7\\x0e\\x8c>\\xe3?\\xd5\\x96\\x8c\\x96\\xc3\\xeb\\xd2\\xbf\\x02\\xd2\\x07.s\\x06\\xfc\\xbf\\xc1\\xee.O\\xa9\\x05\\xe6?}x\\x8bPm\\'\\xf7?\\x8d\\x87\\n\\x0e\\xee\\x1c\\x8d?q\\x19tq\\x1abcbuiltins\\nslice\\nq\\x1bK\\x00K\\x08K\\x01\\x87q\\x1cRq\\x1d\\x86q\\x1eRq\\x1f\\x85q ]q!(cpandas.core.indexes.base\\n_new_Index\\nq\"cpandas.core.indexes.base\\nIndex\\nq#}q$(X\\x04\\x00\\x00\\x00dataq%h\\x0ch\\rK\\x00\\x85q&h\\x0f\\x87q\\'Rq((K\\x01K\\x08\\x85q)h\\x13X\\x02\\x00\\x00\\x00O8q*\\x89\\x88\\x87q+Rq,(K\\x03X\\x01\\x00\\x00\\x00|q-NNNJ\\xff\\xff\\xff\\xffJ\\xff\\xff\\xff\\xffK?tq.b\\x89]q/(X\\x02\\x00\\x00\\x00x0q0X\\x02\\x00\\x00\\x00x1q1X\\x02\\x00\\x00\\x00x2q2X\\x02\\x00\\x00\\x00x3q3X\\x02\\x00\\x00\\x00x4q4X\\x02\\x00\\x00\\x00x5q5X\\x02\\x00\\x00\\x00x6q6X\\x02\\x00\\x00\\x00x7q7etq8bX\\x04\\x00\\x00\\x00nameq9Nu\\x86q:Rq;h\"cpandas.core.indexes.range\\nRangeIndex\\nq<}q=(h9NX\\x05\\x00\\x00\\x00startq>K\\x00X\\x04\\x00\\x00\\x00stopq?KdX\\x04\\x00\\x00\\x00stepq@K\\x01u\\x86qARqBe\\x86qCRqDX\\x04\\x00\\x00\\x00_typqEX\\t\\x00\\x00\\x00dataframeqFX\\t\\x00\\x00\\x00_metadataqG]qHX\\x05\\x00\\x00\\x00attrsqI}qJX\\x06\\x00\\x00\\x00_flagsqK}qLX\\x17\\x00\\x00\\x00allows_duplicate_labelsqM\\x88sub.',\n", " 'y': b'\\x80\\x03cpandas.core.series\\nSeries\\nq\\x00)\\x81q\\x01}q\\x02(X\\x04\\x00\\x00\\x00_mgrq\\x03cpandas.core.internals.managers\\nSingleBlockManager\\nq\\x04)\\x81q\\x05(]q\\x06cpandas.core.indexes.base\\n_new_Index\\nq\\x07cpandas.core.indexes.range\\nRangeIndex\\nq\\x08}q\\t(X\\x04\\x00\\x00\\x00nameq\\nNX\\x05\\x00\\x00\\x00startq\\x0bK\\x00X\\x04\\x00\\x00\\x00stopq\\x0cKdX\\x04\\x00\\x00\\x00stepq\\rK\\x01u\\x86q\\x0eRq\\x0fa]q\\x10cnumpy.core.multiarray\\n_reconstruct\\nq\\x11cnumpy\\nndarray\\nq\\x12K\\x00\\x85q\\x13C\\x01bq\\x14\\x87q\\x15Rq\\x16(K\\x01Kd\\x85q\\x17cnumpy\\ndtype\\nq\\x18X\\x02\\x00\\x00\\x00f8q\\x19\\x89\\x88\\x87q\\x1aRq\\x1b(K\\x03X\\x01\\x00\\x00\\x008\\xccF\\\\\\xc0\\x9a\\xb8&\\xcb\\x18\\xa1M@f\\x1e\\xcb:\\xf2\\xabT\\xc0\\x0b\\xbe;Jp\\xeeh@\\xf6\\x0f\\xbb\\xa5\\xcc\\x18^@\\x17\\xe6 \\xe8\\xc7\\xeba@\\xd4F\\xfc\\xcf\\xfb\\x8e\\\\\\xc0v\\xbd\\x16\\xe4\\xe2\\xe7p@i\\xb0`\\xbc+\\xc92\\xc0:-f\\x01f\\xeeR@Hy\\x8b\\xbc\\x89M\\t\\xc0/6j\\x00\\xca\\xe5b@\\xbd3\\xac\\xdb\\x84yn@\\xb4\\xd1\\xeb\\x84\\x8e)\\x06@\\xa4\\x96\\x82\\xbe\\xae\\xadB@\\x07\\x8b\\xdc\\xc1\\xd8LX@\\xfe\\x1e\\x8cg\\xc6&d\\xc0\\xf6\\n{\\x0e\\xc2\\x1b3@\\x9b\\xec\\xdfIwRj\\xc0\\xa4\\xa7\\xa5\\x04\\xb1\\x98D\\xc0\\x84\\xee\\x8f\\xcdy\\xd3\\x17@zf5\\xee5\\x7fY\\xc0\\xb9\\x01#\\x02\\xe3\\xd1W\\xc0\\xf3\\x82\\x1cb\\x81Ge\\xc0>z)}\\xfdJ9\\xc0\\x7f\\x9fV\\xa9$/9@\\xb4\\xfbn\\x1dz\\xd7H\\xc0ug\\x8e\\x07\\xa1\\xfc@\\xc0f\\\\\\x0e\\xc8\\x8d\\xaca\\xc0X\\xa7L\\x10k\\xfdP\\xc0\\x92\\xe9\\x8ca*\\xccF@<\\xcf\\xe4\\x92\\xfc\\xa9@@v\\'\\\\\\x93@\\xa7=@\\x9e\\xbd\\x19\\xec\\xd2H2@\\xa26\\xc1Q(T\\x06@\\x19&\\xf0\\xc3\\xc2\\x91M@\\xfb\\x8d\\xbd\\\\A`]@\\xc6\\xf6\\xd6\\xbf\\xc4\\xb13\\xc0\\xfc/k\\xc0\\xb8\\x90@@^yn\\x8aQ\\x82\\x11\\xc0\\xd89\\xd7y\\xd8:W@k;\\xb1@N\\x91H@5\\xce0`\\x9aRf\\xc0\\xd9\\xa6:\\x0c\\xa95_\\xc0\\xf8$\\xe1\\x80\\xed\\xd3f\\xc0\\xf5\\x7f3Hd\\x9fT@\\x88\\xe7\\xe5\\x02y\\xf1_\\xc0\\xcc\\xf3\\xa0\\xbb \\x0bm\\xc0&\\x9dr\\x8b\\xb0iN@\\x9e\\xd8\\x1dM\\xf4\\xe1f@\\x18\\xcf\\xb8\\\\\\xff}P\\xc0\\xf9\\xe0V}u[E@\\xe6t=R\\xc5ip@\\xea\\xa3u\\xac\\xfd\\x81e@\\x00f\\xa3j\\x17\\x82\\xed?\\xec\\xba\\xbds\\xc6\\\\i@\\x90\\xd0\\xb3\\x16\\x97\\x14-\\xc0\\xf8\\xfb\\xd5\\xe7\\x92\"^@q\\x1etq\\x1fba]q h\\x07h\\x08}q!(h\\nNh\\x0bK\\x00h\\x0cKdh\\rK\\x01u\\x86q\"Rq#a}q$X\\x06\\x00\\x00\\x000.14.1q%}q&(X\\x04\\x00\\x00\\x00axesq\\'h\\x06X\\x06\\x00\\x00\\x00blocksq(]q)}q*(X\\x06\\x00\\x00\\x00valuesq+h\\x16X\\x08\\x00\\x00\\x00mgr_locsq,cbuiltins\\nslice\\nq-K\\x00KdK\\x01\\x87q.Rq/uaustq0bX\\x04\\x00\\x00\\x00_typq1X\\x06\\x00\\x00\\x00seriesq2X\\t\\x00\\x00\\x00_metadataq3]q4h\\naX\\x05\\x00\\x00\\x00attrsq5}q6X\\x06\\x00\\x00\\x00_flagsq7}q8X\\x17\\x00\\x00\\x00allows_duplicate_labelsq9\\x88sh\\nX\\x01\\x00\\x00\\x00yq:ub.',\n", " 'model_name': 'LinearRegression',\n", " 'model': b'\\x80\\x03csklearn.linear_model._base\\nLinearRegression\\nq\\x00)\\x81q\\x01}q\\x02(X\\r\\x00\\x00\\x00fit_interceptq\\x03\\x88X\\t\\x00\\x00\\x00normalizeq\\x04\\x89X\\x06\\x00\\x00\\x00copy_Xq\\x05\\x88X\\x06\\x00\\x00\\x00n_jobsq\\x06NX\\x08\\x00\\x00\\x00positiveq\\x07\\x89X\\x10\\x00\\x00\\x00_sklearn_versionq\\x08X\\x06\\x00\\x00\\x000.24.2q\\tub.'},\n", " {'index': 'group0-SVR',\n", " 'group': 'group0',\n", " 'X': b'\\x80\\x03cpandas.core.frame\\nDataFrame\\nq\\x00)\\x81q\\x01}q\\x02(X\\x04\\x00\\x00\\x00_mgrq\\x03cpandas.core.internals.managers\\nBlockManager\\nq\\x04cfunctools\\npartial\\nq\\x05cpandas.core.internals.blocks\\nnew_block\\nq\\x06\\x85q\\x07Rq\\x08(h\\x06)}q\\tX\\x04\\x00\\x00\\x00ndimq\\nK\\x02sNtq\\x0bbcnumpy.core.multiarray\\n_reconstruct\\nq\\x0ccnumpy\\nndarray\\nq\\rK\\x00\\x85q\\x0eC\\x01bq\\x0f\\x87q\\x10Rq\\x11(K\\x01K\\x08Kd\\x86q\\x12cnumpy\\ndtype\\nq\\x13X\\x02\\x00\\x00\\x00f8q\\x14\\x89\\x88\\x87q\\x15Rq\\x16(K\\x03X\\x01\\x00\\x00\\x00M\\xd6?\\xb1\\xf1\\x1d!\\x95)\\xff\\xbf`\\xfe\\xdbQ*{\\xd2\\xbf`\\x1bT`\\\\\\x93\\xec?^C\\x1bp\\xdc\\xba\\xb7?\\xfcmv\\xfa\\xb33\\xe7?r\\x82\\xce)\\x84*\\xf9?\\xd7\\x9f\\xdf:0\\xd6\\x01@\\x17s>\\xe1\\xebF\\xf4?9.^\\x9a\\x8b\\xb5\\xa6?\\xcc\\xcd\\x8a\\xb9Qa\\xbe\\xbf\\xdab\\x03\\x98\\xbdK\\xc1?l\\xc6\\xfa@6S\\xe9?\\x1b\\xe6\\xc5\\x9f\\x13*\\xe6?)\\x1aIl\\xdf\\x88\\xe0\\xbf\\xebg\\xe8\\x01\\x88\\x91\\xdf\\xbf\\xc6\\xe9\\xb3\\xe8\\x94\\xef\\xd7\\xbf\\xda\\x1c\\x17\\x90\\xf5\\xd3\\xa5\\xbf\\x91U\\x9e\\x9c\\'\\x86\\xf2\\xbfF\\xb8\\xea\\x8c\\x0f(\\xe3\\xbf}\\xdc\\x14\\xfdvk\\xf4?\\xffJ\\xe2c\\x19\\xc7\\xc1?\\xe2\\x95\\x86\\x0clZ\\xd5\\xbf+\\xb0\\xa7\\xc1\\xb4\\x98\\xa3?\\x94\\xf7\\xab\\x95J\\xa2\\xf3\\xbf\\xc4\\xef4\\x1e\\xb4\\xa8\\xef\\xbf\\xb4\\x03>\\x80\\xc9\\x04\\xf5?\\xbcm\\x8f\\xdc|;\\xdd\\xbf2\\x10\\xfc\\xe1DF\\x00@w\\xff\\x93\\xa4\\xea\\x08\\xa8?&[\\x9b\\xa8\\xd0\\xdb\\xc3?\\\\>\\xd9)\\xbdo\\xca?\\x87L\\x98\\xda\\xc2U\\xfe?I@\\xb5\\xfdr\\x17\\xce\\xbfB\\xf2t\\xb9\\x19\\xb1\\x9a?:\\xef\\x82,=e\\xe2\\xbf\\xfa\\xb7n\\xc7E\\x95\\xbc\\xbf[oc\\x94\\xd8\\x0b\\xf9\\xbf\\xe4?$\\x91z\\n\\xee?\\x17\\xbb\\rG\\xd6\\xbe\\xd3\\xbff\\xf0\\x03B;\\xda\\xee\\xbf\\x90\\xba\\x8d\\x8a\\x82\\xe5\\xd0\\xbf\\x93aE\\xa1.\\x83\\xe0\\xbfT\\xea\\xd3;\\xe5\\xd6\\xcf\\xde\\x9f\\xfb?\"#\\xc9\\xfa\\xce\\x16\\x1f\\xbf\\xee\\xd6B\\x87\\xea\\x11\\x00@R\\x85>\\xb0 \\x8c\\xf2?b\\x81\\xe6~\\x87\\x83\\xf6\\xbf\\xe3~5\\xed\\x96\\xe9\\xdf?\\x97&~\\x8cD\\xba\\xcb?W,\\x04V\\x13\\x08\\xf1?\\x9c}\\x1ff\\x9dv\\xcf\\xbf9\\x03\\x86G\\x03;\\xf0?\\xd4Nw\\xe1\"\\x8a\\xe3\\xbf\\xa9\\xbe\\x02\\x8b\\xde%\\xd7?\\xd6\\x8cOA\\xd0\\x95\\xd4\\xbf\\x00R\\xe9\\xbd\\xf3_\\xf8\\xbfZju\\xae\\xc5\\xea\\xf1?\\xb9\\xf2N\\xff\\xec\\x05\\xd1\\xbf\\x99\\xad\\x84;\\xcd\\xee\\xe3?\\xaeJ\\x9d\\\\\\x8d8\\xf6\\xbf\\xa7\\x9el\\xba\\x9d\\xb7\\xfe?\\xf2\\xe0@\\x88\\xfc\\x9e\\xd8?\\xa3jR\\x96\\xa9\\xc4\\x01\\xc0\\xbb\\xcc\\x12\\xf8\\xff\\xd4\\xe5\\xbf\\xca\\xf5R\\xcf\\xe6\\x9c\\xe2?\\x0b\\x7f?\\xbe\\x0f\\xf3\\xe7?9?\\xd2&\\x82\\xd5\\xf5\\xbf\\x82\\xcdd\\xca\\xd9t\\xca\\xbf\\x84PVz\\xe1N\\xec\\xbf\\x04\\xd3\\x9blv\\xf1\\t`\\xe0?\\xdc\\x80\\xb5\\xce\\xdb\\xfc\\xe4\\xbf\\xceG\\x1b\\xa7K\\xcb|?\\xf1\\xfa\\x9cB\\xec\\x90\\xea?\\x10\\xe0\\']\\xd2\\xf4\\xe0\\xbf\\xcd9\\xa2B\\xeb\\x8d\\xc7\\xbf\\xa0\\xac\\xeb\\xf2\\xfd#\\xf6?\\xe5\\xb1\\xe1\\t\\xb2\\x1f\\xdf\\xbfH$\\xb6\\x01C\\xbd\\xf6?z\\xdf\\x969\\xfc\\x1b\\xf5\\xbf\\xba^\\xd4h\\xc4\\xa2\\xe4?\\xf3,\\x1e\\x05-\\x0e\\xec?f\\x98\\xe6\\xc9S,\\xf0?%\\x92Eh\\xd3\\x1a\\xb4\\xbfHj\\x8d\\x1a\\xcd\\xcap\\xbf\\xdb\\x12C6\\xd8\\x15\\xee?p\\x86\\xc6\\xc0\\xe2H\\xda?\\x0bb=^\\xcf\\xe0\\xde?\\xd8]\\xa5\\xa9dP\\xf1\\xbf\\xd7f\\xf1\\xd9o\\xe4\\xd3?\\x132\\xfc\\xd1\\x90\\x14\\x03@\\xfb\\x15\\xaa\\x0f<\\xfa\\xd4\\xbf\\x8b\\xf3;\\xbeL\\xac\\xe5\\xbf\\xc7F\\\\/\\xd7\\x92\\xfb?;\\x05\\x06\\xd0s.\\xc3\\xbf\\xa0\\x8e:+\\x99\\xfb\\xd7?V\\x1fJ\\xecN\\xdb\\xa5\\xbf\\xc5+\\xd4\\xf4\\x924\\xe5\\xbfBi\\x8f\\xaa\\x12\\x15\\xdb\\xbffQ\\xd8\\xd1\\x7f\\xcd\\xcc?\\x90=J \\xf6\\n\\xd5?\\xdeq)+\\x9c\\xe5\\x02@._\\xb5\\x1b\\x15\\xc3\\xee?\\xd4\\x944\\x92\\x18<\\xe9\\xbf!\\x94\\xe8\\xeer\\xe7\\xf1?;n!\\x1aX8\\xc7\\xbfQ$\\xa8v\\x84\\xc6\\xe7?\\xc9\\x17\\x92\\xa7B\\x01\\xce?5eCM\\xee\\xad\\xf3?R\\xdeg\\x947\\xd7\\xe6?@\\xc2\\r\\xbb\\xf2J\\xe9?\\t\\xa9r\\x0e\\xd0\\xaa\\xd1\\xbf4\\x01\"\\xcb\\xf5\\x84\\xcd\\xbfm\\x1b\\xd0\\x11\\xd1\\xfd\\xf6\\xbf\\x10x\\x9c~ \\xab\\xed?e\\x9d\\t\\x84\\x8eI\\xeb\\xbf\\xad=\\xf0f\\x8f\\xfe\\x8c?\\xea\\x93\\x14}\"\\xa6\\xda\\xbf\\x98WU\\xb7}c\\xce\\xbf\\xcce\\xa2w_i\\xe1\\xbf)\\xef7L\\xa5\\x7f\\xf5\\xbf\\x93=\\x15k\\x83\\xf9\\xce\\xbfe9\\xbd\\xb6\\xabx\\xdc?\\xa4\\xcbE\\xab\\xc6\\xc0\\xbe?\\xd2\\xcbM\\x8c\\x1d\\x94\\xd3?\\x9ct\\xb0\\x16\\xe4A\\xf1\\xbf!d\\xd2\\x11sZ\\xf4\\xbf\\xe3\\x15P\\x0eq\\xf7\\xee\\xbf\\x1e- \\xab\\x93\\x96\\xc3?\\xae\\xe0\\xcf\\xbe\\xa68\\xd7\\xbf\\xa6\\xa9\\xa9\\xc3J\\x0f\\xaa\\xbf\\x17%+ZfJ\\xb7?\\x00\\xc6Z\\xf8\\x82u\\xf5?\\x94\\xf9#\\x0e\\x05\\xe2\\xe6?g\\x9a\\x0f\\xb5\\xbf\\xf0\\xea?h\\xd5O\\x92\\x11\\xa8\\xf5\\xbf\\x94u_\\xa3k\\xfa\\xf0?\\xeei\\xf2\\x85\\xb9h\\xdb?\\x13\\xe9r\\x1f\\x8dI\\xaa\\xbf\\xaf\\xbc\\x15\\x81\\x895\\xea\\xbf\\x82M\\xd6\\xb3M\\x0f\\xf4\\xbf\\xb2n\\xe2\\x1c\\x96\\xf9\\xe0\\xbf<\\xecT\\xe8\\xf9\\xcf\\xda\\xbf\\x04$\\xb3a\\x94\\xbe\\xf6\\xbf\\xa3\\x85\\xfcH\\xe2\\xad\\xfc\\xbf\\xb7\\xb1:\\xd0\\x16j\\xf1?\\xa4\\xf3\\xa7\\x90\\x92J\\xf4?VqR\\x06\\x9e\\xcc\\xee\\xbfCW\\xc0XN\\xb5\\xd3?\\xfd\\xb4\\xb4s_\\x8f\\xf8?\\n\\x0e\\xa0\\xf7\\xeay\\xfe?\\x9f\\x94JZ\\xc8a\\xe1\\xbf\\xc8\\x8bC\\xea[r\\x02@\\xfa\\xcc\\x03%\\xef\\xe6\\xf3\\xbf^\\xe5\\xdc\\x874i\\xd3\\xbfj4\\x19;P\\x87\\x00@i\\xd6\\xb7+\\xbeP\\x00@\\xd1\\x91\\xc0\\xf9?\\x9f\\xe8\\xbf\\x12\\x02\\x81\\xfb\\xcf\\xf8\\xc7?)a\\xf1\\x9c\\xb9&\\xd1\\xbf\\xd4\\xdf@\\xb2\\xee\\xb7\\x00@=\\x9c\\xe9/\\xf8m\\xe2\\xbf\\x0b0\\xea\\\\a`\\xe9\\xbf\\x1a\\x86\\x85D,\\xeb\\xf1\\xbf\\xb4)\\xe6\\x08\\'\\xb8\\xd9?\\x8a\\xb0EN\\xcb\\x99\\xf2\\xbfr\\xf80\\x93\\x10\\x99\\x03@\\x08\\x83\\xd66&\\xaf\\xdf\\xbf$\\n!\\xdc\\xaaz\\xd8\\xbf\\x17\\xd6\\x04\\t\\xa3\\xb0\\x89\\xbfPY\\x85\\xc8c=\\xac?r\\xff\\xec5U\\n\\xdd?i\\x03\\xd5t#\\xcd\\xf3?\\xf4kc\\x04\\xe5\\xc4\\xe5\\xbf\\x98\\xb1\\xbf=\\x0b\\r\\xd8\\xbf\\xef\\x11\\xc2\\xf7\\xe7\\xd2\\xf3?\\xe92SQ\\x15`\\xe6?6\\xe6\\x8aY\\xe7\\xc6\\xe5\\xbf\\x97\\xce|\\xc2R\\xd5\\xe2\\xbf\\xca\\x87\\xe5\\n\\xb5\\xc2\\xb0?1gA\\x0e\\xc4(\\xe5?\"8\\x02io\\xbe\\xe6\\xbf\\xae56\\xa3-\\xcf\\xdf\\xbf\\x9a\\xb5Vr\\xa1 \\xe0\\xbf\\xce\\x9c\\xee\\x1aVB\\xe9?\\xc0Ub\\xca\\x99\\xd6\\xc2\\xbf\\xa8\\xe7\\xfa96\\x03\\xe3?h)\\xfa\\x0cQru\\xbf\\xe0\\x8f\\x89\\x9d\\x11T\\xca?\\xad\\xb5\\x99mo\\x8b\\xfd\\xbf\\t g0\\x85\\xb1\\xe4\\xbf:6\\xf5\\xe0\\xba\\x16\\xe5\\xbfP\\x1fk\\xb7\\xa5\\xee\\xe4?v#=\\xd2\\x10\\r\\xe3\\xbf\\xd0ExU\\x86\\xfd\\xf7?\\xa5G\\x7fH\\xa3\\xd1\\xc3?\\n\\x85\\x88o\\xe1\\xa0\\xcf?\\xeb\\xa8uJO\\xf0\\x01@\\xc2\\x1c\\xb8\\x84\\xcf\\xd5\\xfc\\xbfS\\x99t\\xf51T\\xfd?\\x9e\\xa5\\xea\\xde\\xacP\\xc2\\xbf\\x1f!Oy\\xe1\\xf0\\xdd\\xbf\\xb7\\xf7\\xea\\x0c\\x8b\\xba\\xe2?9r\\x0e\\xc2\\xa3O\\xdb\\xbf\\x13\\x80\\xa5\\x1ek-\\xd3?h\\xf9\\xe7P!\\r\\x01\\xc0\\n&K&#s\\xf1?\\xa2;\\xe3\\xc9e\\x86\\xb4?\\x95e3\\xdf\\x84\\xbe\\xd5?\\x16Q;\\xdf\\xa5\\xa8\\xe2?!GO|\\x8bh\\xfb\\xbfg\\xc3\\x11\\xc4\\xfaT\\xd7?t\\xd4\\xc2M\\x90?\\xe2?\\xce\\xd5\\x07\\tu\\xf3\\xf1\\xbf\\xc6\\xb9\\r\\x9b\\xfd\\x15\\xf7\\xbfz\\xa0O|7l\\xf0\\xbf=\\x1b\\xf1\\xef4\\xc5\\xed\\xbf\\xc7\\x9a6,\\xa5\\x0c\\xe3?\\xa6\\x05w\\x98\\xf5\\xb9\\xdd\\xbfOb\\xfb\\xd0\\xc3\\xd4\\xf9?\\xfa\\xdc\\xdc\\xae\\x11\\x87\\xe3?\\xa4\\xd0v\\x8f\\x99:\\xf3\\xbf\\xf9nBs\\x8f]\\xe6\\xbf\\xd5{\\'C\\xdb+\\xf8?KO\\xf4D@\\xa7\\xd4\\xbf\\xaa\\x9aM\\x17\\xc2{\\xf9?\\xed3\\xcf\\xce1\\x1c\\xf1\\xbf\\x97\\xd7g\\xf3\\x00\\xfd\\xd5\\xbf\\xb6\\xc93\\x98R\\xad\\xf6?\\xd8\\xdcG\\x15\\xda\\xfb\\xea?\\x19\\xbcM5h\\x01\\xf5\\xbf\\x91\\x0b\\x83\\nQ1\\xc4\\xbf\\x0f\\xe5\\xb3\\xc3\\x9c\\x03\\xed\\xbfF\\xa9y%&l\\x9c\\xbfK$\\x1fZ\\xf9\\xd7\\xe9?\\x06\\x7f\\xba3\\x94t\\xfa\\xbf(\\xec\\x88\\x85\\xa7\\x88\\xfa\\xbf4\\xd5Q]~F\\xd4?C!\\xa8\\xd9\\x0c%\\xe1?\\xe0\\xcb\\xcf^\\x0c\\xc7\\xf1?d\\x9dJ\\x9fYF\\xf4\\xbfm\\xc8\\x0f\\xb6t\\xb9\\xf2?\\x8fu.\\x02C^\\xcc\\xbfB`\\xd8\\xf9L\\x98\\xea?\\xf7(3\\xefm<\\xcc\\xbf\\x8c\\xfa\\xe8\\x9aC\\x1a\\xf2?hj\\xfc\\r:}\\xd7?\\xa9a\\xb6\\x98\\xda\\x0e\\xe8?\\x82\\xb8J\\xfe\\x11\\xd3\\xe2?y\\xd3q\\x7f\\xc6\\x08\\xe8\\xbf[\\r\\xb8\\xce\\x0f\\xd5\\x93\\xbf\\x84U\\xf3\\xf7\\xd6?\\xe9\\x8a\\x80\\xc17\\xc8\\xc8\\xbf\\xffM\\xf1f\\x1b(\\xeb?\\xbb\\x05h\\xe1F\\xd5\\xf7?#\\x97\\'\\x99\\x0c\\xf5\\xe4?\\xfa\\xea\\xc4\\xbc\\x1c7\\xfc\\xbfp\\xc4\\xb3\\x05B\\x81\\xbc?\\xea\\xd7rj\\xb3&\\xda?\\xcd\\xc2Ox\\xe6\\xb3\\xd1\\xbfK\\xfd\\xd3-\\xf7\\xf0\\xe4?\\xd1\\xf1\\xb3\\xd8\\xd8\\xfe\\xda\\xbf\\x9b}i\\xd5,\\xb7\\xfd?*\\x84\\xa5z\\xfc\\xa6\\xd3\\xbf\\xa9x\\n\\x9e\\xd1\\xe3\\xf2?\\xdejAd\\xf3|\\xb6\\xbfI\\x93nOK\\xc7\\xe2?\\xb0\\x04\\xe2D\\xa0\\x80\\xb9\\xbfd\\x0c\\xab\\xd8\\xda\\x98\\xf6\\xbfw\\x8a\\x87\\xf2\\x06\\xa4\\xdb\\xbf\\xe2\\x0f\\xfc\\xf5\\t\\xc5\\xe4?\\x1ezx@9\\xbc\\xfa\\xbf\\xc67\\xec\\xd24 \\xea?\\xd2\\xc5C\\xb3c\\x01\\xea?F\\xf4\\xbe-\\xad\\x83\\xfb?\\xad\\x00\\x04\\xc7\\x98t\\xb3\\xbfz3\\x8e\\x87\\x85\\xf9\\xde\\xbf\\n\\xee8\\xae\\xff\\x1c\\xee\\xbf\\xe3\\x84k\\x1fSb\\xd2\\xbf\\x12\\xa5\\xc2_\\xa5\\xcf\\xd9?\\x14F\\x92\\x19\\x96\\xe0\\xe2?\\xd9\\x81$\\xf3\\xbd\\xb4\\xf4\\xbfJ\\xfda\\xab\\xe3{\\xda\\xbf!GM8\\xdf\\xa4\\xfb?\\xb8/9\\xe0&\\x95\\xe2?\\xc5\\xe9\"\\xf7\\xfa\\xb7\\x08\\xc0N\\xff;\\xcdc\\x0b\\xef\\xbfS&js\\xedX\\xcf?\\xe1yq\\xfaO\\x80\\xee\\xbfg\\x89-\\t\\xf8=\\xe1\\xbf\\x85\\x1e;\\xcb\\xa1\\x11\\xf7?G0\\xf3\\r\\x03\\x93\\xfb?\\xe68\\xac\\xb5\\xda\\xee\\xf9?F\\x9c\\xa2\\xb3M\"\\xe0\\xbfb\\x8ev_\\xebR\\xf8\\xbf\\xf8i\\x1fR\\x99\\xe9\\xfb?\\x88\\xdf\\xd3\\x19\\x14\\x14\\xa7?\\x82W\\xe9\\x96\\xb4(\\x03@\\x89\\xc3\\x07\\x9b\\xad\\xd9\\xcb\\xbfA:\\x1e\\xb3\\xcb\\x93\\xeb\\xbf\\xb4\\x87\\xf8i\\xbf\\xf9\\xb5\\xbf\\xf6\\xe9\\xa2\\xebP\\xa0\\xa0?N,3T\\x1f-\\xfd?a`mL\\x03\\x14\\xf7\\xbf\\xff\\xd8\\xf0\\xbe\\xa2\\xed\\xe7\\xbfX\\x8b\\xcf?\\xb6\\xb7\\xf6?\\xd9\\xf3\\xd3\\xf1\\xdfF\\xf6?\\x18s\\xdc\\xdf\\xe1\\xf9\\xd2?\\xdbSb8\\x7f=\\xe4\\xbf\\xff\\xa5b\\x04\\x91<\\xeb\\xbfl*\\xee\\xe4\\xa2\\x15\\xd2\\xbf%(\\n\\xf1\\x916\\xbd?UH\\xfc\\x95\\x85,\\xf1?\\x05Y\\x8dV\\xcf\\xe2\\xf2?\\xb5z\\x10\\xf8\\xe8/\\xf4?-\\xd2\\xd8\\n\\x84\\x9d\\xe1\\xbfd\\x05V\\xd2c\\xe4\\xf9?U\\x9f\\x92/M\\x18\\xf5?\\x15Y\\xf2\\xb0\\xc1\\xcc\\xfb\\xbf\\x8fq-\\xc9e\\xf7\\x04@\\x8b\\t\\xb0f\\x89Y\\xe4?\\xecV\\x06\\xb6\\xd1\\xbf\\xa3?R\\xd8\\x02\\xcf\\xd2h\\xec?\\x02q\\x84t\\x0c8\\xfa?\\xaf,\\x1b\\x9a^\\x14\\xef\\xbf\\xd8\\r\\xa5\\xed\\x19\\x86\\xda?4e\\xb7\\x90\\xf5\\xaa\\xe1?\\xf1\\xd0\\xc0\\x10\\xb5\\xe7\\xfc\\xbf\"\\xd9Z\\x19\\xbc\\xc5\\xd5?\\xf9\\xba\\x7f\\xb7L\\xa7\\xc8?\\xb8\\x00w\\xe1B\\xa4\\xfa?W\\x8f;\\x8c\\xd7n\\xf9\\xbf< _R\\x158\\xe4\\xbf\\t\\x11\\xff\\xf8,q\\xdb\\xbf#\\xd3\\xb6q\\xf3f\\xd7\\xbf\\tF\\x99$\\xf0\\x14\\xf8\\xbf5V\\x18u\\xb7<\\xd3\\xbfY\\xe6$\\x1b\\xdd|\\xd6?\\x1cT\\xb9\\xe8\\xcc\\x82\\xe5\\xbf\\x86c\\xaa9^,\\xec?\\x82\\xc7\\x16U\\x08s\\xf7\\xbf\\xd1i\\xcf\\x08\\xa0\\x02\\xe6?j\\x0c\\xcd\\x93\\x17E\\xb7\\xbfn\\xdbl\\x1b\\xeb\\xd8\\xf8\\xbf\\xeb\\x82p\\xbf6\\xfe\\xe6?\\xb7\\x05+w\\x01\\xca\\xf8?S\\x8b\\xcc\\xea\\xa8z\\xe0\\xbf\\r\\xe7:\\xb8\\xb6\\xae\\xe7?\\x18\\xc1\\x0b\\xecy(\\xfd\\xbfGG\\x94:\\xba\\xb5\\xea\\xbfBJL\\xc9\\x84>\\xdf?q\\x11\\xb5\\xd8\\xce\\x12\\xe5\\xbf\\xa3\\xae\\x0c#x?\\n\\xc0\\xf5\\xef\\xa7_ys\\xdb?)\\xe7\\xd2\\xd7d\\x9a\\xfb?\\xea\\x855\\xe0\\xa9s\\xe6?.\\xec\\xec\\xdd\\xe53\\xcd?&\\x86\\xb8\\xef\\xefE\\xf6?\\x08\\x83_(w\\x88\\xf9?\\x15\\xdagL\\x0ej\\xd2\\xbf,\\xd1O\\xee\\xdf\\x03\\xea\\xbf\\x8d\\xe2\\xcd`\\x10W\\xe8?\\x8d\\x97\\xed\\x94+\\x18\\xf2?\\x81\\x8aN\\x1cN\\x85\\xf1?\\xa6f\\xa6\\xed\\x14m\\xcd?\\xf4\\xb8\\x80\\xa7e{\\xf8\\xbf<2\\xc2>\\xac\\xb2\\xd8\\xbfE\\xc7U\\xae\\xce\\xf1\\xfd?\\xbe\\xd9\\x14\\'T\\x93\\xdd?8\\xd4,\\x87\\x98o\\x8a\\xbf\\x02\\xfb\\x14\\'`;\\xe3?\\xa6\\xfb\\x03;\\xbei\\x88\\xbf\\xf3\\xfe\\xbe\\xedp\\x12\\xfd?\\xd5\\x87\\xc4$c(\\xde?\\xb6\\xd8\\xabb\\x8e\\x0f\\xa3\\xbf\\xca\\xdc\\x9b\\xa0\\xf9\\xd8\\xf7?\\xb0\\xcd>\\x17=q\\xe7?(\\x9aAL:\\x14\\xc7\\xbf\\x8c\\xae\\xdbH\\x94\\x94\\xe1\\xbf\\xe7\\xc7\\xc5W\\xa1\\xa9\\xe3\\xbf^T\\x82\\x9arV\\xcd\\xbf\\xab\\xbdE\\xd9\\xaa0\\xef?>\\xd1\\xeeNp\\xdf\\xe1\\xbf\\xad\\xc7\\xeb{\\x08\\xa8\\xe4?\\xa7r\\xe0\\xa8\\xa2\\x93\\xe2\\xbf7y\\xe7,\\x15H\\xd9?25|\\\\\\xda\\xe2\\xf3\\xbf)\\x9f\\x16>\\x8e\\x04\\xf8\\xbf`U\\xfe\\x005\\xd4\\xef\\xbf~\\x01CQ\\x07\\xbe\\xd4\\xbf\\x11\\xb5\\xd8\\xed\\x06\\x94\\xea?j\\xe6\\xa2r-\\xa7\\xfe\\xbf\\x0e\\x15~\\xcc\\x97\\x19\\xed?\\x11\\xe45!\\x14\\xbd\\xcc?>706M4\\xf4\\xbf\\x16\\x1d\\xc6u\\xb9\\x1f\\xe1?<\\x17\\xcb\\x94\\xd9\\x9d\\x03@\\x04\\x18\\xd6\\x1f\\xec\\xff\\xaa?C6[\\x1fc\\xc5\\xb2?Z\\xef\\xcd\\xd4\\xd5N\\xf1\\xbfR\\xd7\\x04J\\xda\\x0e\\xe2?\\x80]x\\xc1\\x01e\\xdb?\\xff\\xf7\\xf3\\xb4\\x11Y\\xee\\xbf\\xd2\\tH\\xc1\\xb8\\x8f\\xde?\\x98\\x8e\\x05\\x8e\\x1b\\x96\\xec\\xbf?\\x14\\xb9\\x95\\xe8-\\xee?\\x19\\x92C\\x97a\\xc3\\xc6?\\x91\\xe9.4f\\xc3x\\xbf\\xf0!8\\x95\\xc9\\xdf\\xca\\xbf\\xdf\\xe7iQtF\\x9f?\\x17\\xb7\\x91\\xd6\\xe5?\\xe4\\xbf\\x07 2\\xce\\xc0_\\xed?|\\x99\\x16\\x14\\xda\\xc5\\xf2?IoVi\\x1d6\\x02\\xc0\\xcfbq\\xc0\\x94\\xcf\\xec?.H\\xde\\x12\\x89\\x1a\\xf1\\xbf\\x81\\x9a\\x940\\xf9\\x07\\xf3?0\\xfc\\x8dzlW\\xe0\\xbf\\x89\\x95\\x17\\x84\\x1b\\xd7\\xa5?\\xdaq\\xdax<\\xac\\xec?D\\xb7\\x13>\\xd0\\x97\\xf1?\\xde\\x06\\xf9\\xb4\\xb9\\x96\\xf7?\\xf3\\xfd\\xe6kt<\\xe7\\xbf\\x95\\xcbn\\xb1\\xff\\xbd\\xe4?JI\\xd4\\x18\\x97\\r\\x00@\\xfa\\xbc\\xaa\\xad/\\x97\\xfa\\xbf-\\r%\\xc7\\x1c\\x1c\\xd5?\\xddq\\xbe\\xf9\\xae\\xd2\\xc3?\\x05E5h\\xcd\\xe1\\xc2?\\xc9\\xef\\x82B\\x87\\x03\\xf4\\xbf\\xa7\\xf3}\\xa7\\x8a\\xda\\xf4\\xbf\\x1b\\x96\\x1c\\xc07\\xd1\\xf0?)\\xa1\\xa0u\\x87\\xf0\\xe1?\\x8b}\\x90\\xe1\\x10s\\xed?\\xae-;\\xfbu:\\xd9\\xbfI5\\xd91w\\xc8\\xdd?T\\xf0m\\n\\xadi\\xf4?J\\x0b\\x02_\\x81M\\xd7?\\xd6\\xa2F\\x9b\\x9c\\x9b\\xc3\\xbf\\xfdq)I\\xa2\\x05\\xe1?U8\\x14\\xdc\\xee\\xf3\\xdc\\xbfy\\x12\\x08\\x92\\xf5\\xda\\xed?V\\x04N#\\xbc\\x82\\xf7?\\xe4\\x07\\xc4r\\x88\\x1a\\xc0\\xbf\\xe5o!6f\\x92\\xf2?\\xc0\\xbc\\x1b\\xef\\x80\\xac\\xe1\\xbfA\\xfeR\\xd3v\\xa3\\xb8\\xbf\\xb2\\xd6\\x83\\xa6\\xcas\\xe6\\xbf\\xcc\\x0e4f\\xe8\\x1d\\xf4\\xbf\\xbc@gb\\xbf\\xa9\\xfb\\xbf\\xf5\\x00\\xf6a\\x91\\xd4\\xf6?\\x88\\x90\\x91\\xb8-\\'\\x02\\xc0\\xa5A\\x12\\xb8\\xd9\\x0b\\xe8\\xbf10\\x89\\xd4\\x0bz\\x04\\xc0\\xee5S\\xdc\\x83Z\\xe0?\\t=H\\x90\\xea\\x8d\\xda\\xbf.\\x8b\\x07\\x8d\\ri\\xf9\\xbf\\xba\\x01\\xa5\\xd3\\xc0\\\\\\xd1?\\x13\\xa8L\\x9b\\xc9\\xa3\\x01@nzG^\\x16\\xac\\xe5\\xbf\\x9b\\\\L\\x05\\xde\\xd3\\xdd? \\xc5\\xb2\\x08;\\xc8\\xce\\xbf\\xc0e:mx\\xa7\\xf5?\\x1ch\\xc8k\\xa7P\\xe9\\xbf=\\x86\\xd5o\\xfe\\x00\\xd2\\xbf\\x19\\x8b\\xd3\\xd4[\\xb9\\xbe\\xbf\\x9c\\x19\\xea0=\\xba\\xdd\\xbf.1K\\x87\\x00>\\xe7?@\\xc6\\xa1\\xbf]R\\xcf?}\\xa5\\x0f\\xeb\\x83{\\xa0\\xbfQ\\xc6\\xd7\\x1d2\\x8e\\xe3\\xbf\\xc7+\\xe1\\x80bu\\xcd?\\x97H\\n\\x11\\x7f\\xda\\xd6?\\xa4M 8\\xb0\\r\\xe2?\\xbb\\xcb\\xb2WK\\x87\\xeb\\xbf\\xf6\\x8e\\xbe\\xd7\\x07T\\xe6\\xbf\\xe8\\xc6\\xe8@\\xbf\\x8d\\xf9\\xbf\\xb6%\\x98O#\\xd2\\xf3\\xbf$6y\\xd5P!\\xc1?\\xf4\\xe5k\\x17\\xefw\\xf1\\xbfqU\\xa7\\xa5\\xd4\\xa7\\xd6?J\\xba}\\x16\\xfcw\\xd6\\xbf\\x1a&\\xb3\\x02\\xe8\\xa1\\xd6\\xbfP\\xc2\\xf0\\xc9\\x8e\\xd3\\xea\\xbf\\xa4Y\\xd3v\\x9b\\xf3\\xc9\\xbf\\xbd!\\x94\\xc1a\\x1f\\xef\\xbf\\xb4L\\x82\\xad\\x80.\\xfb?\\x91s\\xe3\\x06\\xea\\xac\\xf0\\xbf\\xb4\\xfd]\\xe3\\x13&\\xc1?U\\xa3\\x96\\xc7\\xd9\\x02\\xe2\\xbf\\xfd\\x04\\x03i\\x02\\xbd\\xc9\\xbf\\xee\\xb6\\xf3mF\\x1c\\xd9?\\xf0o\\x1cn \\xd0\\xe8?\\xb9\\n\\xc0}\\xbc!\\xda\\xbf\\xe0\\x06Y\\xd1\\xcd`\\xf6\\xbf\\x1e{q\\xa3\\xe0r\\xe2?\\xc3 W\\xe7\\x88Q\\xf5?\\xc5O\\xaf\\x89\\xf9\\xe0\\xde?P\\x89\\xf9|\\xda7\\x01@\\xed\\xce\\xac\\x04\\xeb\\xb7\\xdc\\xbf\\x0e\\x1f\\x1fSd\\x85\\xd1?p\\xff\\xd6D\\x91_\\xe2\\xbfmQu\\xaf\\x134\\xba\\xbf\\xa9B,`W\\\\\\xe3\\xbf\\x0f\\xb0!\\xfc\\xf1o\\xf1?\\xcf\\xe7{\\xbbak\\xd2\\xbfTf\\xf8\\x83\\t\\xce\\xeb?\\xdf\\x9a\"\\xc6\\xb0o\\xe1\\xbfT\\xb7a\\xf0p\\x8a\\xe9\\xbf\"\\x03\\xd5\\x1e\\xaa\\x1d\\xf1?\\x03w\\xccd\\x19\\xfd\\xf1\\xbf\\xdd\\xfcfS\\xbb\\xbf\\xe9?eP\\x190\\x8d.\\xb4?X\\x01d\\x92\\xc9\\xba\\xf4?Dw\\x02\\xc89\\xea\\xf2\\xbfB\\x81)>\\x12\\x16\\xf1?n\\xc9\\xadKF\\xc1\\xe7\\xbf\\x84\\xbb8Y-\\x90\\xeb?j\\xb6\\xf3A\\xe6\\x95\\xcf?p\\xe5\\x9e+KV\\xe3?\\xee\\xc1-\\xe5I)\\xe9\\xbf\\x18\\x8b\\x91\\xc9\\x89\\xcc\\xeb\\xbfA\\xbf\\xb6}\\xe4\\x00\\xeb\\xbf4\\xbb(\\xe6\\x01\\xd0\\xe6?\\xfe\\n\\xf5Z\\x9c\\xf3\\xd0?;\\xf0A\\xe8\\x92\\xe0\\xf4?\\xdf;\\x95i\\xad\\x15\\xc6\\xbf\\xcaZ\\x0c\\n\\xc6\\xa3\\x02\\xc0$\\x06\\xbam\\xb0\\x85\\xec\\xbf\\x13=)U\\xd9o\\xe7?\\xcd\\xd1\\xd1w\\xf9\\xea\\xfd\\xbf\\xf4\\xc4\\x8b,\\xc5=\\xe0\\xbf\\xdf\\xec\\xb7\\xa5\\xd3\\xd1\\xf2\\xbf\\xe4\\xb09P \\xf4\\xe1?S\\xa6\\xd9\\xcdl\\x87\\xbe?\\xa5\\x8cE\\x11(\\x8f\\xfa\\xbf.GkY\\xcd\\xac\\xf7\\xbfbS\\xef\\xbb,z\\xea\\xbf\\x1f\\x82S\\xd9\\x900\\xc1\\xbf\\xd8v/\\xb4\\xb0\\xad\\xc1\\xbf\\xe3\\x02\\xa6\\x9b\\t\\x08\\xc5\\xbf2~\\x8d\\xbe=\\xe4\\xe2?uf\\x8f\\xfb:\\x89\\xff?\\x1f\\xee\\x192\\x84\\x9d\\xce\\xbf@r\\n\\x96\\x16\\xf6\\xad?\\xb8\\x9a\\t\\xff\\xea\\x87\\xd2?q\\r\\xee$\\xe7\\x85\\xe3?\\xb0\\xee\\x19j}\\x18\\xf7?\\xf6{\\xbdlt\\xff\\xd1\\xbf\\x06Y\\xd8\\xf5\\x17\\xa7\\xf3\\xbf>\\tl\\xec\\xc6>\\xde\\xbf\\xd8.\\x85v\\x7f\\xd7\\xf3\\xbf\\xb3\\xc4\\x1c\\x12\\xab\\xbe\\xe9\\xbf\\xc2M\\x8b\\xbe\\xb0\\xd6\\xd3?\\xca=\\xea\\x13\\xd0F\\xe7?\\x1e\\x89\\x8f\\xe2P\\x17\\xb7?j\\xc2\\n\\xa9\\x10$\\xd6\\xbfr\\x1b2\\xee\\xe7\\xbf\\xf4\\xbf\\xe5k\\r\\x9c}u\\xdd\\xbf\\x83\\xcdz\\xe6\\x9d\\x88\\xd9\\xbf\\xab\\xea\\xf78#\\xc2\\xf1?\\xfb\\x9b\\xcc\\xf3*&\\xce?\\xc3\\x08z\\x95k\\x85\\xb3?\\xe2F\\x14\\xb0\\x8e\\xd6\\xe4?\\xfe\\xa2\\xb3\\xc4\\xea*\\xde?\\xd9\\xfc\\xbf\\x86\\xc0\\xbe\\xd1?\\xec\\xa8\\xdc\\x91Q\\xa4\\xe2?\\x8dWR/n;\\xea\\xbf${\\xac\\x8e\\x8e\\x7f\\xdc\\xbf\\xee\\x87\\tC6\\xae\\xdf?j\\xfd\\xec+7\\xad\\xd0?3_\\xda\\xc0]\\x07\\xf5?\\x081\\x1f\\x83\\xe5\\xff\\xeb\\xbfS\\xe9j\\x96B\\x86\\xd5?\\xab\\r\\xd9\\xadj\\xcf\\xec?\\xe7\\xbdE\\xaf*9\\xf6?\\xce$g\\xcc\\xb5\\xb1\\xcd\\xbf\\xc6R\\xd0\\xb3\\xd1,\\xf2?=;\\x10\\xe3\\x92\\xe3\\xf8\\xbf\\xbc\\x81\\xd3x~\\x12\\xf0\\xbf&\\xfd\\xc0\\xcbr\\x15\\xd9?\\xd8\\x15\\x9c\\x9adv\\xee?\\xb5\\xd3{#\\x1a\\x8a\\xe6\\xbf\\xa0\\x9e\\x1e\\x88\\xeb\\xf4\\xb8?\\xb3g\\x1d\\xf4\\xa4\\x89\\xd8?\\xeb\\xddz\\xf0h\\xcc\\xc7?\\xfa8\\x8b\\xf8(\\xca\\x00@\\xd6\\x1fe]\\xc4\\xe3\\xd1?\\x0brOf\\xbe\\xf5\\xca?\\xe7&\\xfa\\x9c\\xd6S\\xe0?\\n V&O\\xed\\xc3?\\xd8\\x19\\x1b\\x98\\xf2\\xeb\\xef?\\x8a3\\xaf\\xd5\\xd7\\x1c\\xa1?\\x03\\xb3v\\xfb_\\xb3\\xf0?\\x8c\\xbe\\xd8\\x884\\x97\\xf0?h~v\\x97\\xbd\\x8d\\xc3\\xbf\\xbbT\\xaaZ\\x10\\x1e\\xe3?\\x1c\"\\xadU|\\xa6\\xe1?\\xda\\x962\\x9a\\xc6;\\xf7\\xbf\\xef\\xc4+ \\xc5e\\xc7\\xbf[\\xcf5F\\xfa\\x83\\xb5\\xbf\\x129zk\\x87k\\xc2?E\\x96]n\\t \\xe2?1\\x02\\x8d\\xa7\\xb67\\xd6?K\\xfa-\\xed\\x99g\\xfc?\\xccZ!A\\xb6\\x03\\xca\\xbf\\xb2tV\\xc5D\\xfc\\xdf\\xbf\\xbc\\x00\\x1f\\x9dp\\xcb\\xf3?\\xeb\\xfb\\xec\\xa7\\'c\\x01\\xc0:Y*\\xc3\\xb58\\xd3?fD\\xa6w\\x1f\\xac\\xff\\xbf\\r\\xde\\x02\\x11Y\\xff\\xec?\\x90w\\x80\\x91s\\x9b\\xfe\\xbf\\x0e\\x82\\xef\\x18=\\x92\\xe1\\xbfd4\\xb8\\xb3\\xb7\\xf6\\xac\\xbf\\xe6Td\\xb1\\xb1\\xb8\\xda?\\xa5\\x8fn\\xc4\\xa2\\x80\\xe9?%\\x05\\x86\\xc4\\x93\\xfb\\xde?GP\\xba7\\xde\\xab\\xfe?E?\\xd0Fz\\xb0\\xb8?~\\xb0M\\xb1tE\\xe1?P\\xde\\xf7\\x0e\\x8c>\\xe3?\\xd5\\x96\\x8c\\x96\\xc3\\xeb\\xd2\\xbf\\x02\\xd2\\x07.s\\x06\\xfc\\xbf\\xc1\\xee.O\\xa9\\x05\\xe6?}x\\x8bPm\\'\\xf7?\\x8d\\x87\\n\\x0e\\xee\\x1c\\x8d?q\\x19tq\\x1abcbuiltins\\nslice\\nq\\x1bK\\x00K\\x08K\\x01\\x87q\\x1cRq\\x1d\\x86q\\x1eRq\\x1f\\x85q ]q!(cpandas.core.indexes.base\\n_new_Index\\nq\"cpandas.core.indexes.base\\nIndex\\nq#}q$(X\\x04\\x00\\x00\\x00dataq%h\\x0ch\\rK\\x00\\x85q&h\\x0f\\x87q\\'Rq((K\\x01K\\x08\\x85q)h\\x13X\\x02\\x00\\x00\\x00O8q*\\x89\\x88\\x87q+Rq,(K\\x03X\\x01\\x00\\x00\\x00|q-NNNJ\\xff\\xff\\xff\\xffJ\\xff\\xff\\xff\\xffK?tq.b\\x89]q/(X\\x02\\x00\\x00\\x00x0q0X\\x02\\x00\\x00\\x00x1q1X\\x02\\x00\\x00\\x00x2q2X\\x02\\x00\\x00\\x00x3q3X\\x02\\x00\\x00\\x00x4q4X\\x02\\x00\\x00\\x00x5q5X\\x02\\x00\\x00\\x00x6q6X\\x02\\x00\\x00\\x00x7q7etq8bX\\x04\\x00\\x00\\x00nameq9Nu\\x86q:Rq;h\"cpandas.core.indexes.range\\nRangeIndex\\nq<}q=(h9NX\\x05\\x00\\x00\\x00startq>K\\x00X\\x04\\x00\\x00\\x00stopq?KdX\\x04\\x00\\x00\\x00stepq@K\\x01u\\x86qARqBe\\x86qCRqDX\\x04\\x00\\x00\\x00_typqEX\\t\\x00\\x00\\x00dataframeqFX\\t\\x00\\x00\\x00_metadataqG]qHX\\x05\\x00\\x00\\x00attrsqI}qJX\\x06\\x00\\x00\\x00_flagsqK}qLX\\x17\\x00\\x00\\x00allows_duplicate_labelsqM\\x88sub.',\n", " 'y': b'\\x80\\x03cpandas.core.series\\nSeries\\nq\\x00)\\x81q\\x01}q\\x02(X\\x04\\x00\\x00\\x00_mgrq\\x03cpandas.core.internals.managers\\nSingleBlockManager\\nq\\x04)\\x81q\\x05(]q\\x06cpandas.core.indexes.base\\n_new_Index\\nq\\x07cpandas.core.indexes.range\\nRangeIndex\\nq\\x08}q\\t(X\\x04\\x00\\x00\\x00nameq\\nNX\\x05\\x00\\x00\\x00startq\\x0bK\\x00X\\x04\\x00\\x00\\x00stopq\\x0cKdX\\x04\\x00\\x00\\x00stepq\\rK\\x01u\\x86q\\x0eRq\\x0fa]q\\x10cnumpy.core.multiarray\\n_reconstruct\\nq\\x11cnumpy\\nndarray\\nq\\x12K\\x00\\x85q\\x13C\\x01bq\\x14\\x87q\\x15Rq\\x16(K\\x01Kd\\x85q\\x17cnumpy\\ndtype\\nq\\x18X\\x02\\x00\\x00\\x00f8q\\x19\\x89\\x88\\x87q\\x1aRq\\x1b(K\\x03X\\x01\\x00\\x00\\x008\\xccF\\\\\\xc0\\x9a\\xb8&\\xcb\\x18\\xa1M@f\\x1e\\xcb:\\xf2\\xabT\\xc0\\x0b\\xbe;Jp\\xeeh@\\xf6\\x0f\\xbb\\xa5\\xcc\\x18^@\\x17\\xe6 \\xe8\\xc7\\xeba@\\xd4F\\xfc\\xcf\\xfb\\x8e\\\\\\xc0v\\xbd\\x16\\xe4\\xe2\\xe7p@i\\xb0`\\xbc+\\xc92\\xc0:-f\\x01f\\xeeR@Hy\\x8b\\xbc\\x89M\\t\\xc0/6j\\x00\\xca\\xe5b@\\xbd3\\xac\\xdb\\x84yn@\\xb4\\xd1\\xeb\\x84\\x8e)\\x06@\\xa4\\x96\\x82\\xbe\\xae\\xadB@\\x07\\x8b\\xdc\\xc1\\xd8LX@\\xfe\\x1e\\x8cg\\xc6&d\\xc0\\xf6\\n{\\x0e\\xc2\\x1b3@\\x9b\\xec\\xdfIwRj\\xc0\\xa4\\xa7\\xa5\\x04\\xb1\\x98D\\xc0\\x84\\xee\\x8f\\xcdy\\xd3\\x17@zf5\\xee5\\x7fY\\xc0\\xb9\\x01#\\x02\\xe3\\xd1W\\xc0\\xf3\\x82\\x1cb\\x81Ge\\xc0>z)}\\xfdJ9\\xc0\\x7f\\x9fV\\xa9$/9@\\xb4\\xfbn\\x1dz\\xd7H\\xc0ug\\x8e\\x07\\xa1\\xfc@\\xc0f\\\\\\x0e\\xc8\\x8d\\xaca\\xc0X\\xa7L\\x10k\\xfdP\\xc0\\x92\\xe9\\x8ca*\\xccF@<\\xcf\\xe4\\x92\\xfc\\xa9@@v\\'\\\\\\x93@\\xa7=@\\x9e\\xbd\\x19\\xec\\xd2H2@\\xa26\\xc1Q(T\\x06@\\x19&\\xf0\\xc3\\xc2\\x91M@\\xfb\\x8d\\xbd\\\\A`]@\\xc6\\xf6\\xd6\\xbf\\xc4\\xb13\\xc0\\xfc/k\\xc0\\xb8\\x90@@^yn\\x8aQ\\x82\\x11\\xc0\\xd89\\xd7y\\xd8:W@k;\\xb1@N\\x91H@5\\xce0`\\x9aRf\\xc0\\xd9\\xa6:\\x0c\\xa95_\\xc0\\xf8$\\xe1\\x80\\xed\\xd3f\\xc0\\xf5\\x7f3Hd\\x9fT@\\x88\\xe7\\xe5\\x02y\\xf1_\\xc0\\xcc\\xf3\\xa0\\xbb \\x0bm\\xc0&\\x9dr\\x8b\\xb0iN@\\x9e\\xd8\\x1dM\\xf4\\xe1f@\\x18\\xcf\\xb8\\\\\\xff}P\\xc0\\xf9\\xe0V}u[E@\\xe6t=R\\xc5ip@\\xea\\xa3u\\xac\\xfd\\x81e@\\x00f\\xa3j\\x17\\x82\\xed?\\xec\\xba\\xbds\\xc6\\\\i@\\x90\\xd0\\xb3\\x16\\x97\\x14-\\xc0\\xf8\\xfb\\xd5\\xe7\\x92\"^@q\\x1etq\\x1fba]q h\\x07h\\x08}q!(h\\nNh\\x0bK\\x00h\\x0cKdh\\rK\\x01u\\x86q\"Rq#a}q$X\\x06\\x00\\x00\\x000.14.1q%}q&(X\\x04\\x00\\x00\\x00axesq\\'h\\x06X\\x06\\x00\\x00\\x00blocksq(]q)}q*(X\\x06\\x00\\x00\\x00valuesq+h\\x16X\\x08\\x00\\x00\\x00mgr_locsq,cbuiltins\\nslice\\nq-K\\x00KdK\\x01\\x87q.Rq/uaustq0bX\\x04\\x00\\x00\\x00_typq1X\\x06\\x00\\x00\\x00seriesq2X\\t\\x00\\x00\\x00_metadataq3]q4h\\naX\\x05\\x00\\x00\\x00attrsq5}q6X\\x06\\x00\\x00\\x00_flagsq7}q8X\\x17\\x00\\x00\\x00allows_duplicate_labelsq9\\x88sh\\nX\\x01\\x00\\x00\\x00yq:ub.',\n", " 'model_name': 'SVR',\n", " 'model': b'\\x80\\x03csklearn.svm._classes\\nSVR\\nq\\x00)\\x81q\\x01}q\\x02(X\\x06\\x00\\x00\\x00kernelq\\x03X\\x03\\x00\\x00\\x00rbfq\\x04X\\x06\\x00\\x00\\x00degreeq\\x05K\\x03X\\x05\\x00\\x00\\x00gammaq\\x06X\\x05\\x00\\x00\\x00scaleq\\x07X\\x05\\x00\\x00\\x00coef0q\\x08G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00X\\x03\\x00\\x00\\x00tolq\\tG?PbM\\xd2\\xf1\\xa9\\xfcX\\x01\\x00\\x00\\x00Cq\\nG?\\xf0\\x00\\x00\\x00\\x00\\x00\\x00X\\x02\\x00\\x00\\x00nuq\\x0bG\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00X\\x07\\x00\\x00\\x00epsilonq\\x0cG?\\xb9\\x99\\x99\\x99\\x99\\x99\\x9aX\\t\\x00\\x00\\x00shrinkingq\\r\\x88X\\x0b\\x00\\x00\\x00probabilityq\\x0e\\x89X\\n\\x00\\x00\\x00cache_sizeq\\x0fK\\xc8X\\x0c\\x00\\x00\\x00class_weightq\\x10NX\\x07\\x00\\x00\\x00verboseq\\x11\\x89X\\x08\\x00\\x00\\x00max_iterq\\x12J\\xff\\xff\\xff\\xffX\\x0c\\x00\\x00\\x00random_stateq\\x13NX\\x10\\x00\\x00\\x00_sklearn_versionq\\x14X\\x06\\x00\\x00\\x000.24.2q\\x15ub.'}]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "create_training_manifest(df, models=[LinearRegression(), SVR()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Using Fugue transform()**\n", "\n", "Now that we know the functionw orks, we can then use the `Fugue transform()` function to generate the `training_manifest`. This interprets the `List[Dict[str,Any]]` output type of the `create_training_manifest()` function and brings it out to a pandas DataFrame (and Spark or Dask later). " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
indexgroupXymodel_namemodel
0group0-LinearRegressiongroup0b'\\x80\\x03cpandas.core.frame\\nDataFrame\\nq\\x00...b'\\x80\\x03cpandas.core.series\\nSeries\\nq\\x00)\\...LinearRegressionb'\\x80\\x03csklearn.linear_model._base\\nLinearR...
1group0-SVRgroup0b'\\x80\\x03cpandas.core.frame\\nDataFrame\\nq\\x00...b'\\x80\\x03cpandas.core.series\\nSeries\\nq\\x00)\\...SVRb'\\x80\\x03csklearn.svm._classes\\nSVR\\nq\\x00)\\x...
\n", "
" ], "text/plain": [ " index group \\\n", "0 group0-LinearRegression group0 \n", "1 group0-SVR group0 \n", "\n", " X \\\n", "0 b'\\x80\\x03cpandas.core.frame\\nDataFrame\\nq\\x00... \n", "1 b'\\x80\\x03cpandas.core.frame\\nDataFrame\\nq\\x00... \n", "\n", " y model_name \\\n", "0 b'\\x80\\x03cpandas.core.series\\nSeries\\nq\\x00)\\... LinearRegression \n", "1 b'\\x80\\x03cpandas.core.series\\nSeries\\nq\\x00)\\... SVR \n", "\n", " model \n", "0 b'\\x80\\x03csklearn.linear_model._base\\nLinearR... \n", "1 b'\\x80\\x03csklearn.svm._classes\\nSVR\\nq\\x00)\\x... " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from fugue import transform\n", "\n", "training_manifest = transform(df, \n", " create_training_manifest, \n", " schema=\"index:str, group:str,X:binary,y:binary,model_name:str,model:binary\", \n", " params=dict(models=[LinearRegression(), SVR()]))\n", "training_manifest.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**One training run**\n", "\n", "Each row in our `training_manifest` represents a model training run. All we need to do is pull the metadata, unpickle it, and then run the `.fit()` and `.predict()` method of the model. We then store the mean_absolute_error of the training run so that we can evaluate these later. This is done in the `training_run()` function below.\n", "\n", "Because Fugue lets us be flexible about type annotations, we can use the `List[Dict[str,Any]]` structure for both input and output to make our logic easier to write." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def training_run(df: List[Dict[str,Any]]) -> List[Dict[str,Any]]:\n", " training_sample = df[0]\n", " index = training_sample[\"index\"]\n", " group = training_sample[\"group\"]\n", " X = pickle.loads(training_sample[\"X\"])\n", " y = pickle.loads(training_sample[\"y\"])\n", " X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)\n", " model = pickle.loads(training_sample[\"model\"])\n", " model.fit(X_train, y_train)\n", " y_pred = model.predict(X_test)\n", " mae = mean_absolute_error(y_test, y_pred)\n", " return [dict(index=index,\n", " group=group,\n", " model_name=training_sample[\"model_name\"],\n", " error=float(mae),\n", " model=pickle.dumps(model))]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then test it by passing `List[Dict[str,Any]]` from the first row of our `training_manifest`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'index': 'group0-LinearRegression',\n", " 'group': 'group0',\n", " 'model_name': 'LinearRegression',\n", " 'error': 8.757634740955517,\n", " 'model': b'\\x80\\x03csklearn.linear_model._base\\nLinearRegression\\nq\\x00)\\x81q\\x01}q\\x02(X\\r\\x00\\x00\\x00fit_interceptq\\x03\\x88X\\t\\x00\\x00\\x00normalizeq\\x04\\x89X\\x06\\x00\\x00\\x00copy_Xq\\x05\\x88X\\x06\\x00\\x00\\x00n_jobsq\\x06NX\\x08\\x00\\x00\\x00positiveq\\x07\\x89X\\x0e\\x00\\x00\\x00n_features_in_q\\x08K\\x08X\\x05\\x00\\x00\\x00coef_q\\tcnumpy.core.multiarray\\n_reconstruct\\nq\\ncnumpy\\nndarray\\nq\\x0bK\\x00\\x85q\\x0cC\\x01bq\\r\\x87q\\x0eRq\\x0f(K\\x01K\\x08\\x85q\\x10cnumpy\\ndtype\\nq\\x11X\\x02\\x00\\x00\\x00f8q\\x12\\x89\\x88\\x87q\\x13Rq\\x14(K\\x03X\\x01\\x00\\x00\\x00\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
indexgroupmodel_nameerrormodel
0group0-LinearRegressiongroup0LinearRegression11.190594b'\\x80\\x03csklearn.linear_model._base\\nLinearR...
1group0-SVRgroup0SVR76.397862b'\\x80\\x03csklearn.svm._classes\\nSVR\\nq\\x00)\\x...
\n", "" ], "text/plain": [ " index group model_name error \\\n", "0 group0-LinearRegression group0 LinearRegression 11.190594 \n", "1 group0-SVR group0 SVR 76.397862 \n", "\n", " model \n", "0 b'\\x80\\x03csklearn.linear_model._base\\nLinearR... \n", "1 b'\\x80\\x03csklearn.svm._classes\\nSVR\\nq\\x00)\\x... " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "training_results = transform(training_manifest, \n", " training_run, \n", " schema=\"index:str,group:str,model_name:str,error:double,model:binary\",\n", " partition={\"by\": \"index\"})\n", " \n", "training_results.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Multiple Models for Each Group\n", "\n", "Everything above is now scale agnostic and we can bring the logic to Spark. We previously ran these on Fugue's default `NativeExecutionEngine`, which is sequential. In practice, doing a grid search can take multiple hours. Parallelizing the training runs over Spark or Dask will allow us to iterate faster and fully utilize compute.\n", "\n", "We make a new larger DataFrame that contains 10 distinct groups. We want to train the models for each of these groups separately." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "df = make_data(groups=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All of our logic remains the same. We simple use the `SparkExecutionEngine` to scale and speed up our model training. The same thing can be done with the DaskExecutionEngine." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pyspark.sql import SparkSession\n", "spark = SparkSession.builder.getOrCreate()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+--------------------+------+----------------+----------+--------------------+\n", "| index| group| model_name| error| model|\n", "+--------------------+------+----------------+----------+--------------------+\n", "|group3-LinearRegr...|group3|LinearRegression| 9.379544|[80 03 63 73 6B 6...|\n", "| group2-SVR|group2| SVR| 75.86907|[80 03 63 73 6B 6...|\n", "|group9-LinearRegr...|group9|LinearRegression| 9.286413|[80 03 63 73 6B 6...|\n", "|group4-LinearRegr...|group4|LinearRegression| 6.1316595|[80 03 63 73 6B 6...|\n", "|group6-LinearRegr...|group6|LinearRegression| 9.684757|[80 03 63 73 6B 6...|\n", "|group1-LinearRegr...|group1|LinearRegression| 5.3616314|[80 03 63 73 6B 6...|\n", "| group9-SVR|group9| SVR|114.082726|[80 03 63 73 6B 6...|\n", "| group1-SVR|group1| SVR| 141.20859|[80 03 63 73 6B 6...|\n", "| group6-SVR|group6| SVR| 91.27704|[80 03 63 73 6B 6...|\n", "| group5-SVR|group5| SVR| 85.69009|[80 03 63 73 6B 6...|\n", "|group2-LinearRegr...|group2|LinearRegression| 6.46798|[80 03 63 73 6B 6...|\n", "|group5-LinearRegr...|group5|LinearRegression| 7.961879|[80 03 63 73 6B 6...|\n", "| group8-SVR|group8| SVR| 92.93862|[80 03 63 73 6B 6...|\n", "|group0-LinearRegr...|group0|LinearRegression| 6.80798|[80 03 63 73 6B 6...|\n", "|group8-LinearRegr...|group8|LinearRegression| 7.6318617|[80 03 63 73 6B 6...|\n", "| group7-SVR|group7| SVR| 140.42226|[80 03 63 73 6B 6...|\n", "| group0-SVR|group0| SVR| 81.492325|[80 03 63 73 6B 6...|\n", "| group4-SVR|group4| SVR| 87.68793|[80 03 63 73 6B 6...|\n", "| group3-SVR|group3| SVR| 118.69519|[80 03 63 73 6B 6...|\n", "|group7-LinearRegr...|group7|LinearRegression| 7.0831575|[80 03 63 73 6B 6...|\n", "+--------------------+------+----------------+----------+--------------------+\n", "\n" ] } ], "source": [ "training_manifest = transform(df, \n", " create_training_manifest, \n", " schema=\"index:str,group:str,X:binary,y:binary,model_name:str,model:binary\", \n", " params=dict(models=[LinearRegression(), SVR()]),\n", " partition={\"by\": \"group\"},\n", " engine=spark)\n", "\n", "results = transform(training_manifest, \n", " training_run, \n", " schema=\"index:str,group:str,model_name:str,error:float,model:binary\",\n", " partition={\"by\": \"index\"},\n", " engine=spark)\n", "\n", "results.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extending this Setup and Fugue Tune\n", "\n", "There are two hyperparameter tuning approaches that can be used with this setup. First is Grid Search, where we try different combinations of hyperparameters. This can easily be inserted into the `create_training_manifest()` function to create more runs. The second is Bayesian optimization (with packages like [Optuna](https://optuna.readthedocs.io/en/stable/)) where a starting point is initialized and then the hyperparameters are optimized through successive runs. This type of logic can easily go into the `training_run()` function we defined above.\n", "\n", "Fugue actually provides a much simpler interface for this type of hyperparameter tuning with the Fugue [tune](https://github.com/fugue-project/tune) library that is built on top of the Fugue core. This library can be used for more serious hyperparameter tuning." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.9 64-bit", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.9" }, "orig_nbformat": 2, "vscode": { "interpreter": { "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" } } }, "nbformat": 4, "nbformat_minor": 2 }