{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "TODO:\n", "\n", "* implement Algorithm 1 \n", "* apply it to the example from [here](https://medium.com/analytics-vidhya/shap-part-3-tree-shap-3af9bcd7cd9b#:~:text=SHAP%20(SHapley%20Additive%20exPlanation)%20is,from%20it's%20individual%20feature%20values.&text=f%E2%82%9B()%20represents%20the%20prediction,model%20for%20the%20subset%20S.)\n", "* use shap to reproduce the manually calculated outputs" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import shap\n", "import matplotlib.pyplot as plt\n", "from sklearn.tree import DecisionTreeRegressor, plot_tree" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import test_tree_shap" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# for auto-reloading external modules\n", "# see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython\n", "get_ipython().magic(\"load_ext autoreload\")\n", "get_ipython().magic(\"autoreload 2\")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "data, tree = test_tree_shap.toy_tree()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import tree_shap" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "assert tree_shap.naive_tree_shap(tree, current_node=0, features={0: 150}) == 20\n", "assert tree_shap.naive_tree_shap(tree, current_node=0, features={1: 75}) == 27\n", "\n", "# given feature 0, having feature 1 doesn't make a difference\n", "assert (\n", " tree_shap.naive_tree_shap(tree, current_node=0, features={0: 150, 1: 75})\n", " == 20\n", ")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import itertools" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "features_tuple = ((0, 150), (1, 75), (2, 200))" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "23.0" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "basis = data['y'].mean()\n", "basis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Need to rename the variables here to make it more readable**" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "all_phis = []\n", "for permutation in itertools.permutations(features_tuple):\n", " phis = {'basis': basis}\n", " for i in range(len(permutation)):\n", " phi_raw = tree_shap.naive_tree_shap(tree, current_node=0, features=dict(permutation[:i + 1]))\n", " phi = phi_raw - sum(phis.values())\n", " phis[permutation[i][0]] = phi\n", " all_phis.append(phis)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/html": [ "[{'basis': 23.0, 0: -3.0, 1: 0.0, 2: 0.0}, {'basis': 23.0, 0: -3.0, 2: 0.0, 1: 0.0}, {'basis': 23.0, 1: 4.0, 0: -7.0, 2: 0.0}, {'basis': 23.0, 1: 4.0, 2: 0.0, 0: -7.0}, {'basis': 23.0, 2: 0.0, 0: -3.0, 1: 0.0}, {'basis': 23.0, 2: 0.0, 1: 4.0, 0: -7.0}]" ], "text/plain": [ "[{'basis': 23.0, 0: -3.0, 1: 0.0, 2: 0.0},\n", " {'basis': 23.0, 0: -3.0, 2: 0.0, 1: 0.0},\n", " {'basis': 23.0, 1: 4.0, 0: -7.0, 2: 0.0},\n", " {'basis': 23.0, 1: 4.0, 2: 0.0, 0: -7.0},\n", " {'basis': 23.0, 2: 0.0, 0: -3.0, 1: 0.0},\n", " {'basis': 23.0, 2: 0.0, 1: 4.0, 0: -7.0}]" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all_phis" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "basis 23.0\n", "0 -5.0\n", "1 2.0\n", "2 0.0\n", "dtype: float64" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame(all_phis).mean(axis=0)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "from collections import OrderedDict" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unhashable type: 'slice'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mOrderedDict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfeatures_tuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'slice'" ] } ], "source": [ "OrderedDict(features_tuple)[:2]" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "[(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]" ], "text/plain": [ "[(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(itertools.permutations(OrderedDict(features_tuple)))" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "((2, 200), (1, 75), (0, 150))" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "permutation" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "[23.0, 0.0, 4.0, -7.0]" ], "text/plain": [ "[23.0, 0.0, 4.0, -7.0]" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phis" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "((2, 200), (1, 75), (0, 150))" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "permutation" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-3., 0., 0.],\n", " [-3., 0., 0.],\n", " [ 4., -7., 0.],\n", " [ 4., 0., -7.],\n", " [ 0., -3., 0.],\n", " [ 0., 4., -7.]])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.array(all_phis)[:, 1:]" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.33333333, -1. , -2.33333333])" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.array(all_phis)[:, 1:].mean(axis=0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0, 1, 2)" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "itertools.subpermutation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0, 1, -2, -2, 0, -2, -2])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.feature" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "array([[[15.]],\n", "\n", " [[40.]],\n", "\n", " [[50.]],\n", "\n", " [[30.]],\n", "\n", " [[10.]],\n", "\n", " [[20.]],\n", "\n", " [[10.]]])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.value" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[1, 0, 0, 0, 1, 1, 0]])" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.decision_path([[150, 75, 200]]).todense()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 1, 2, -1, -1, 5, -1, -1])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.children_left" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 4, 3, -1, -1, 6, -1, -1])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.children_right" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([100., 300., -2., -2., 200., -2., -2.])" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.threshold" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADnCAYAAAC9roUQAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzdd1QUVxvA4d+lI1gACyBgRREEEcWGBbH3buwVS/KpSUzsJfYSNbFrEgv2nsSusUaNGnvvBaWqsYDSYef7Y3EjLhhAZCn3OcdzYOfOzLvj8nKZufe9QlEUJEmSpMyhp+sAJEmSchOZdCVJkjKRTLqSJEmZSCZdSZKkTCSTriRJUiaSSVeSJCkTyaQrSZKUiWTSlSRJykQy6UqSJGUimXQlSZIykUy6kiRJmUgmXUmSpEwkk64kSVImkklXkiQpE8mkK0mSlIkMdB2AlPWYmpqERkfHFNF1HDmBiYnxk6ioaGtdxyFlHUIWMZfeJ4RQ4l8G6zqMHMHAwhZFUYSu45CyDnl7QZIkKRPJpCtJkpSJZNKVJEnKRDLpSpIkZSKZdKX/FPrkKSXKVyYgMAgAlUpFtXpN2blnP6B+WFSpVn1u3LoDQFBwCN5N21Cuck18mrcjJPQJADdu3aFSrfoYF7TPtNg79R6AdenylPWokeT1+Ph4+v7vK8p61MCtujfHT/6t2Xb0xEncqntT1qMG/Yd8Q0JCQrLH3vLbDspVrkmZitUZO3nGJ30fUs4hk670n6yLFGb0t1/xv29GAbDw5xU42BWlRdNGAOjr63P++EGcncoAMGrCVLp2bMfNcyfo0LoFYydPB8DZqQznjx9M8/lfvHyZ7tj79+7Onm3rtV5ftX4TMTGx3L5wkrW/LKb/kG9QFAWVSsWAId+yceXP3L5wkvDXb1i3eZvW/mFh4QwfN4nDu7Zx4+xxjh7/iz//OpXuOKXcQyZdKVV8e3Yl/PVr5ixYwg8LljBv5pQU2+7ef5DundoD0KNzR3bs+SPN5wsPf83y1euo06Q1X48cn+64fWrXxNLCQuv1X3fsoU+PLgC4lXfG0tKCi1eucvbCJWysi2h+gfTu1plfd+zW2n//oSPUqVkDG+siGBgY0KNzR35Lpp0kvU9OjpBSRQjBglnTqFizHvO/n4qNdfJzJ56/eIGZWR5MTEwAMDPLg6GhAWFh4eTPn++D51CpVBw+doLV6zfz97kLtGzWiIWzp+PqUg6A2NhYqtdrmuy+gwf60qtrp1S/n6DgEOyL2mq+d7CzJTAomPj4hPdeL0pgkPaY5cDgEOzeaWdvV5T9h46k+vxS7iWTrpRqu/cfxNbGmms3bqXY5mMm27Tr1oe/z11g4ezprFwyD319/STbjYyM0nV7IjkpxZna+OWkIim9ZNKVUuX+Q39+Xrma04f20LB1R06dOUf1KpW12llZWhIREUl0dDQmJiZEREQSGxv3n71cgKnjR7Ny3QZGT5zGjj376fpZO+rVqYWenvouWEb2dO2K2hIQFIxjqZIAPA4MpqitLfHx8QS807N9HBhEUVsbrf3ti9py9fpNzfcBgUHYJdNOkt4n7+lKqfL518OZPHYktjbWLJwzgy++HkFcXJxWOyEETRvWY83GrQCs3rCZFk0apuoczk5lmDX5O66fOUbHtq1Yvno9TpW8mLfkF+Dfnm5y/9KScAHatGjKitXqB2xXrt3gn3+e41HBlcoVKxAUHKIZibFy7QbatNBO9I3q1eXo8b8ICX1CfHw8qzdspnUy7STpfTLpSv9p9YbNCCHo+lk7ALxr1qBiBVd+WLg02fbTvhvN2k1bcarkxaZftzNl3Mg0nU9fX5+mDeuxceVPnDm6T/NQKz1adOxOzYYt8H8cQDGXSsz4YQEAPbt0xNDQkLIeNejq+zk/L5iDEAJ9fX1+mj+bz3r1o0zF6pib5aHbZ+qHgjv37Kf/kG8AyJ8/HzMnjaNus7Y4e9aitld16tbySnecUu4hC95IWtJa8Ma4oD0x/wR8svbZmSx4I71P9nSlj1aooFWSyREpeTs5wrpI4UyKTJKyHtnTlbTI0o4ZR/Z0pffJnq6UY838cQFlKlbHwMI2yVjbh48eU8W7EZVq1ce1Wh3GT/0+xWPMX7oMp0pelPWoweJfVmZG2FIOJ4eMSTmWT51adGrXBp/mbZO8bmtdhGP7tmNiYkJsbCy1m7TGp05NvGsmrc9w9/4Dli7349yff6AoCp7ejWjSsB4lijlk5tuQchjZ05U+mnFBe76b9j0eNevjWachl69ep3XnnjhV8uLbsRM17b4cPoZqPk1wr+FDj/6DiImJASAqKoovvh5BtXpNca/hw6KfV2RIXJ4e7hRzsNOO19hYM2MuLi6e+Lg4hNC+A/Dbzj10aNMSc3Mz8uY1p23LZvy+a2+GxCblXjLpSh8tISEBV+dyXDhxkNo1a9CxZz9WLJ7L5ZOH2fb7Tvwfq0cqjB/5DacP7+XSycNYWhRg1frNAMz4cQEVK7hy+tAe/j6yl9UbNif7UK7XwCFUqlVf69/gb0elOebnL17gUbM+1o7l8alTizpe1bXaqKcKF9V872BXNMnECUlKD3l7QfpoQghaN28CgLurC6GhTzRFZsqWKY3/4wCKO9izY89+flqxmujoGMLCw1GpVADsO3CYqOholi73AyD89Rvu3LuvNT7Xb+n8DIvZytKSCycO8uyf57Ts1IPrN2/jUq5skjbyIbP0KcikK300PT09DAzUHyU9oYexsXGSbfHx8fg/DmDSjDmcObqfQgWtWPjzcq5cuwGok9vqnxfi7lr+g+fpNXAIV6/f0Hq9RlVPFsyenq7YCxW0olb1qhw48qdW0lVPFQ7SfP9YTvWVMoBMulKmCA9/jampCRYF8hMZGcnaTdtwS6we1qi+DwuWLuPn+XPQ19fn7v0HFClUiHz58iY5Rkb1dAMCgyhoZYmpqSmvX7/hyLETTP1utFa71s2b0LpzT4YN+R+KovDrjt3J1uaVpLSQ93SlTOFW3pk6XjVwqVKbBq0/o4qHu2bbmG+/xNzMDI+a9alQvS4DvhxGbFzsR59z6uy5FHOpRGBwCNXqNaV1554AXL91h+r1muFRsz41G7agU/s2NPTxBuCnFav5bpp6CFmZ0qXo37sHlWo3oFLtBgwa0IeSxYt9dFxS7iYnR0ha5OSIjCMnR0jvkz1dSZKkTCSTriRJUiaSSVfK0lat36Qpp5iZoqKiaNTmM6yKOdGwdcck28LDX9OqUw+cKnlRtW5jbt6+m+nxSdmXTLqSlAwDAwNGDh3Cqp8WaG2bNX8x5Z3Lcev8X3w3ahiD0jE5Q8q9ZNKVUi0yMpJ23fpQ0aseFarXZezkGQDsPXCYGg2aU7l2A6rXb8aFy1cA8H8cgKN7Nb74egSu1epQv2UHLl65SqM2n+HoXo25i3/WHNu4oD1jJk3HvYYPnnUaJlkK5y2VSsXYyTOoVq8pFb3qMWbS9A/G9TEMDQ2pW8sLc3MzrW2/7dxN38SVhJs2rMfd+w94/uLFR59Tyh3kOF0p1fYfOkrhggXZtlZdG+Hlq1cAVPP04MT+Hejp6XHh8hUGDxvDX3/sBNSJt1e3Tiz+cSbtu/dlyLAx/PH7JiKjonCqVJOBfXpgYmJCQkICdrY2XDp5mB179uE76Gv+PrIvyflXrd8EwOlDe1CpVLTt2pu9Bw4THR2dbFzv8n8cQLuuvZN9X9MmjKVRPe9UX4fA91YSLmprQ2BQCFaWlqk+hpR7yaQrpZpbeWdGjJ/MN2MmUN+7Ng196gAQ+uQZPfoP5nFAIAYG+tx76K/Zp6iNNVUqVQSggqsLUVHRmJqaYmpqSkErS0KfPqO4gz0APTqr7522bNqYvv8bSkREZJLz7z1wmCvXbrD3D/WKwBGRUdx78ICmDesnG9e7ijvYZ9hKwpL0MWTSlVKtVIninD26n4NHj7Fmw2YW/7KSnZvXMOjbUfTr2ZVO7dvw+vUbCpYop9nn/SnBxsZG73wviI+PT/X5FUVh5qSxtGrWRGtbcnG9KyN7una2NgQEBWsmSgQFh1DU1jrV+0u5m0y6UqoFBgVjaVGAdq2aU71KZTxq1QcgPDycorbqP7d/9lvzoUN80NpNWxnQpwe79h2gZHEHzMzyJNneuH5dlq5YTaN6dTExMSE4JFRT2yG5uN6VkT3d1s2bsnz1eqaOH8WePw5RqkRxClpZZcixpZxPJl0p1a7euMWYidMQAhQF5s2cAsDEMSPwHfQ1+fKa06ZFs3QdW19fn4CgYCp61cPAQJ/li+ZqtenTvQuBwSFUrdsEIQR5zPKwYtGPPHwUkGxcH6uiVz1Cnjzh9ZsIirlUYtr40XT9rB3DhnxB9/6DcKrkRV5zM/yWao9wkKSUyGnAkhZdTAPOqSsEy2nA0vvkkDFJkqRMJJOulCXkxF6uJCVHJl1JkqRMJJOulCkmzpjN1NnaD8cyw4fqKEycMRs7J3fNemvTZs9L9hiy3oKUUeToBSnHe1tHISIikvlLf9Ha/rlvL8Z8+9UHj/G23sL2javZ88chBn07ikM7t36qkKUcTPZ0pTQbP/V7Zvzw7zCprb/vpJvvF0DKy6y/q88XX7Fu0zbN92U9amhWDL5y7Qb1W3agincjajdulWwNhrT6UB2F1JL1FqSMIpOulGZdOrRh49bfNN9v2PobnTu0BVJeZj014uLiGPj1cFYtnc+Zo/uZM20i/b/8Vqud/+OAZJdir1SrPvsPHU3z+1nmt5aKXvVo160Pd+8/SLZNSvUWJCmt5O0FKc2cyjhiZGTIlWs3cLAvyrmLl9m48ieAFJdZT43bd+9z49ZtWn7WXfPai5faxWsycnbZgN49GP3NlxgaGrL51+207tyT62eOZ8ixJSk5MulK6dKpfRs2bP0Nx1IlaNG4IYaGhh9cZv1dBgb6qJR/k3F04i0IRVEoVbzYfybUjKyjYF2ksObrjm1b8fWo8Tx/8UKrYpistyBlFJl0pXTp1K41tRu3ongxByaOHgZ8eJn1dxV3cODCpSt079SBk3+fJTgkFACnMqV5/SaCQ38ep16dWiiKwqWr16jo5vre/hnX0w0OCcXWRp08jxz/C0MDAywtLLTayXoLUkaRSVdKF1sba0oUL8ZD/0fUqOoJJF1mvWBBK6p4uGt6se/y7dmVtl17417Dh5rVq2pKOxoaGrJt7Qq+GjmOYWMmEhcfR+vmTbWSbnqkVEdh9MRpXLpyDX19PczNzdmyZjlCqGftNu/QjQmjh1G5YgVZb0HKMLL2gqRFLsGecWTtBel9cvSCJElSJpJJV5IkKRPJpCtJkpSJZNKVJEnKRHL0gqTFxMT4iYGFbRFdx5ETmJgYP9F1DFLWIkcvSGkmhBgATADaKYpyUsfhZDohRDFgN3AE+EpRlAQdhyRlIzLpSqkmhNADpgNtgKaKotzTcUg6I4QoAGwFIoHOiqJE6DgkKZuQ93SlVBFCmAIbgRpA9dyccAEURXkFNAX+Af4UQtjoOCQpm5BJV/pPQohCwCEgAWigKMpzHYeUJSiKEgv0BX4HTgkhyus4JCkbkElX+iAhRBngFOr7l10VRYnWcUhZiqI2BRgDHBZC1Nd1TFLWJpOulCIhRC3gGDBdUZQxiqKkvk5jLqMoyjqgA7BOCJF8CTRJQj5Ik1IghOgMzAO6KYryh67jyS6EEGWBPcB6YLwif8Ck98ikKyUh1CW2RgEDgOaKolzVcUjZjhCiMLADuA/0URRFu9SalGvJ2wuShhDCEPgFaI96hIJMuOmgKMpToC5gAhwQQlj+xy5SLiKTrgSAECI/6gH/1kBtRVFkbcePoChKFOp7vGeAk0KIUjoOScoiZNKVEEI4ACeAu0BrRVHe6DikHEFRFJWiKN8C84ETQojquo5J0j2ZdHMhIURZIcTsxK89gJPASmCQoijxOg0uB1IUZTHgC+wQQrQD9VRqIURz3UYm6YJ8kJYLCSEWA0+Ac4AfMFBRlG06DSoXSPwFtwOYC9wGxiiKUk23UUmZTfZ0cxkhRD6gExALLANayISbORRFuQBUB3qgnkJsI4SopNuopMwmk27u0x14BvRGXSmssxCioU4jyiUSZ/eNBRYAzkAUMFinQUmZTt5eyGWEEC8AcyAa9b3cI8BqRVFCdBpYLpBYNKgP6uFk3kAe1MPKrBOHmUm5gEy6uUziA7RdwMnEgi2SDiSWySwP9ANGyREjuYdMupIkSZlI3tOVJEnKRDlijTRTI4PQ6LgEuaZXBjEx1H8SFRtvres4cgJTU9PQ6Oho+dnMICYmJk+ioqKy9WczR9xeEEIo//h9oeswcoyCvRajKIrQdRw5gRBCFhrLQEKIbP/ZlLcXJEmSMpFMupIkSZlIJl1JkqRMlCOT7pNXkVQYupqg568BUKkUGkzcyt6LDwH1PUvvcZu4HfQCgA3Hb1Fj9AYK9V7M6Tv/zhEIi4jBe9wmbPouJfhF5gyjbD9rB97jNlFr7EZ6L9zH66h/h9JO2nwKz+FrqTJiHTvP3te8fjPwOT7fbcFzxDq6z9vLm+i4ZI994mYQXqM34Dl8LV+uOEKCSq6+owuhoaE4ODgQEBAAgEqlokqVKuzYsQNQ37d0d3fnxo0bAAQFBVG7dm3KlCmDt7c3ISHqz+iNGzdwd3fHwCBznodfunQJLy8vXFxcKF++PPPnz9dsi4+Pp3fv3pQuXRoXFxeOHz+u2Xb06FFcXFwoXbo0vr6+JCQkJHv8zZs3U6ZMGUqVKsWYMWM++fvRlRyZdIsUyMPQlpX4dvUxAH45eAU7K3OaVCwBgL6e4OjkzyhbVF1bukLxQqwZ0oTqZWyTHCe/mTFHJ3+GdQGzNJ3/5Zv0r9244n+NODr5M45P6YSthTmL910C4M/rAZy5F8rpGV3YPrIVYzf8pUmu3676k3EdqnJ2ZldKWefX7PMulUrh65VHWPG/Rpz9vhtvomLZcvJOuuOU0s/a2pqxY8fy+eefA7BgwQIcHBxo2bIlAPr6+ly6dAlnZ2cARowYQbdu3bhz5w4dO3Zk9OjRADg7O3Ppkvb/9X958eJFuuLOkycPK1as4Pr165w8eZIFCxZozu/n50dMTAz37t1jw4YN9O3bF0VRUKlU+Pr6smXLFu7du0d4eDhr167VOnZYWBjffvstf/75J7dv3+bIkSP8+eef6Yozq8uRSRegRx1nXkfFsnDvRRbtu8T0brVSbOtsb0Up6wIfdb7o2Hh+PX2XjrN30mPBvnQfJ18eY0CdJKPj4lGvngM7zz2gc00n9PX0sLEwp4qjNUevPeZpWCSBz99Qt7wDAF1rl2PXuftax7348ClFCphpftF0rV2OnecepDtO6eP069eP8PBwZs+ezezZs1mwYEGKbXft2kWPHj0A6NmzJ9u3b0/z+cLDw1m2bBm1atXiyy+/TFfMZcqUoWzZsgDky5ePcuXKaXrr27Ztw9fXFwA3NzesrKy4ePEiZ8+exdbWVvMLpG/fvmzbpl1fad++fXh7e2NjY4OBgQE9e/ZMtl1OkCPG6SZHCMH33WtTe9wmZnarlebeamqduxfKhhO3+PN6IN7l7RnW2hPP0v8OI2z7/Q5evI7S2q+lZymGtqyc7DF7zN/L6TshlLOzZGInLwCCX7yheaWSmjZ2VnkJevGG4JdvKGpp/t7rEVrHDH7xfjvzTLtlImkTQrBo0SLc3NxYuHAhNjY2ybZ7/vw5ZmZmmJiYAGBmZoahoSFhYWHkz5//g+dQqVQcPnwYPz8/Tp8+TevWrVm8eDGurq4AxMbGUqVKlWT3/fLLL+ndO+VFje/fv8+5c+fw8/MDIDAwEHt7e832t7dP4uPjk339fcntv29f+jsvWVmOTboAf1z2x7qAGTcCn3+S449ed5x1x28xqVMNpnWthbGhvlabX4e3TPNxVw9pQmx8Al8uP8LOs/fpXMuJlEZ6pnYIqBwpmvXs2rULW1tbrl5NeSm6jxnj26ZNG06fPs3ixYtZtWoV+vpJP59GRkbpuj3x6tUrWrduzbx587C0tPxgnKmNPzeNZc6xSffh0zD8jlznwHftafv9ds7eC03SA80InzdyJ38eY5buv8zhq4/5rEZZ6lcohpHBvx/u9PR0AYwM9GlTtTSr/7xB51pOFLU0J+idnmng89d4lCiMrYX267aW2r167f3fYGPxaXr/0n+7f/8+S5cu5ezZs9SrV49Tp05Rvbr2aj5WVlZEREQQHR2NiYkJERERxMbG/mcvF2D69OmsWLGCkSNHsn37drp37069evXQ01PfVUxPTzcyMpJmzZrRr18/OnTooHnd3t6egIAAHB0dAXj8+DF2dnbEx8cn6dm+ff199vb2XLly5T/b5QQ59p7uN35/MrpdVWwszJjVow7f+B0lLj75p6bpZV8wLyPaVOHktM4MaFiBfZf8qTpiPZM2n9K0+XV4S45O/kzrX3IJ93VULKGv1LcGVCqFfZf8cUq8B9u8Ukk2nLhFgkpFyMs3/H03BO/y9hQpkIeiluYcufYYgHXHbtLsndsQb7mXKETIywjNiI11x27SvLJ2OylzDBgwgKlTp2Jra8uSJUsYMGAAcXHao06EEDRr1ozVq1cDsGrVKs0Dt//i7OzM7NmzuXXrFp06deKXX37B0dGRuXPnAv/2dJP7l1zCjYuLo23btjRo0IAhQ4Yk2da2bVuWLVsGwJUrV3j27BkeHh5UrlyZwMBAzUiM5cuX07ZtW61jN27cmCNHjhASEkJ8fDyrVq1Ktl1OkCN7uhtP3EII6FhDfdO/ZrmiuBUrxOJ9l/myuYdW+w3HbzHt1795/jqKXgv2YWNpxpGJHVN9PiEENcraUqOsLZExcZy4GZSuuN9Ex9F9/h5i4xJQKVCpZGGGtlAvLOBd3p6j1wOoOmI9Qk8wuZMXeU2NAJjVszaDfjnM8DXHKWNjwdIB9QH1w7OZv51h49Dm6Ovp8WNvb3ov2k9sXAI1nGw110fKXKtWrUIIQbdu3QDw9vbGw8ODOXPmMHLkSK32M2bMoEuXLsyaNQsbGxs2bNiQpvPp6+vTtGlTmjZtyqtXrzh79my64t68eTMHDhwgNDSU33//HYCxY8fSvn17evXqxYkTJyhdujRGRkYsX74cIQT6+vosW7aM9u3bExMTQ506dejevTsAO3bsYMeOHSxbtoz8+fMza9YsateujUqlomPHjtStWzddcWZ1ubL2QpE+S3iy4vNUt6/4zRp2j2mD7TsPonIyWXsh46Sn9oKBgQHx8alfHzSt7bMzWXshm7LKa5pkckRK3k6OiEtQoaeXrf+fpWykUKFCSSZHpOTt5Ahr62xddCvXyZU9XenDZE8348gqYxlL9nSlDDVv1wUqD1tLwV6LtcbQ/vTHZTxHrMNz+FqWH0x5iFFKU4UlKa1mzJhBqVKlEEIQGBiYYruEhASGDh1KmTJlKFeuHOPHj9dsu3PnDj4+Pjg7O+Pk5MT58+cBGDhwIO7u7ri7u+Ps7IyBgUG6Z8plNznyQVp2Vcu5KG2rOdJy+u9JXr8f+ooVh69zZGJHFEXBZ8IW6lcoRrFC+ZK0e3eq8NOwSBpP/pW6rg6Ymxhm5tuQcoh69erRuXNn6tSp88F2s2bNIiYmhtu3byOEIDQ0FEDzQGzRokV4eXkRHR1NTEwMAEuXLtXsv3btWlavXq0Z85vT5cqkW6TPEr5qXol9Fx+ipydY0NeH6b+e4U7ISxq7F2dyZ/UssJFrjnPuQSgxcQm42Fsxr48Pxob6RMXGM3b9Ca48+ofouHh6ervgW9/1o+PyKJn8AgO7zz+gdZXSmuTZsnJJdp9/wBeN3ZO0S2mqcPPKpT46NunTMTAwYPTo0Wzfvh19fX1WrlzJuHHjuHnzJi1btmTOnDkADB48mNOnTxMdHU2FChVYvnw5xsbGREVF8fXXX3PhwgWioqIYMGAAgwYN+ui4PD09U9VuwYIFXL16VTNl/e095gMHDlCiRAm8vNQ/TyYmJpqZde9at26dZkRDbpArk26CSsHZzpJRbaswdsNf9F64jz/GtyePsSFVRqyjX31XHArlY3gbTyzN1R+SUWuPs+HELXrVdWHurgu4FS/EnF7exMQl0HTqr9QqV1RT1+CtL34+yI0A7dlwVRxt+L5H7VTHG/wiAmd7K833Ra3ycj/0VTLtkp8qLGVtCQkJuLq6MmnSJIYOHUq7du04c+YMZmZmODo6MnjwYIoXL86ECROwslJ/DoYMGYKfnx8DBgxg+vTpeHh4sHTpUmJiYvDy8tL8Sf+uHj16JJmA8JaXlxeLFi1KV+xhYWHExcUxZ84c9u/fj4WFBXPmzMHNzY1bt25hampK8+bNCQoKombNmsyaNStJ4n369CmnTp1i69at6Tp/dpQrk64QaCYQuDpY8eRVBBaJydXRpgCP/3mNQ6F87L3wkJVHrhETl0B4ZCyqxAciB688Ijo2npWHrgHwOjqOe6GvtJLu4v71MyReJZWTeOXjmuxJCEGbNm0AcHd3JyQkRPOntpOTE/7+/hQvXpzt27ezZMkSoqOjCQsLQ5VYmnPPnj1ERUWxePFiQF3c5vbt21pJ9+0Ei4wUHx/Ps2fPKFmyJOfOnePQoUO0a9eOu3fvEh8fz+HDhzl//jzW1tb4+voya9Ysxo0bp9l/w4YNNG/eHDOz3DM7MlcmXT0hMNBXP0MUQmD8zrRdPSFIUKl4/Cyc738/y6EJHSiYz5RfDlzhWmKvVVFg6YAGuBYr+MHzZFRP9/0pvEHPX2NroT1mOKWpwlLWpqenp6mJq6enh7GxcZJt8fHx+Pv7M2HCBM6fP0+hQoVYsGABly9fBtR1C9atW4e7u3uyx3/rU/R0raysyJMnDx07qicT1atXj7CwMF69eoW9vT1eXl4ULVoUgA4dOvDzzz8n2X/t2rVMmTIlXefOrnJl0k2N19GxmBgZUMDMmMiYODafvKP5E7++mwM/H7jC3D7e6OvpcT/0FYXz59HMEHsro3q6TSuVpOvcPQxuWhFFUdhx7gFbvmmu1a55pZLM3nGOTjXL8jQskr/vhvBDL+8MiUHSrfDwcExNTbGwsCAyMpI1a9bg5uYGQJMmTZg3bx7Lli1DX1+fu3fvUqRIEfLlS/qg9VP0dAHatWvHwYMHaV6p5DAAACAASURBVNOmDRcvXsTExIQCBQrQuHFjJk6cqKmIduDAAVxcXDT73b59m6CgIOrXz5ifk+xCJt0UuNgXxMvJluqj1mOV1xSPkoWJjlPXbhjaohITNp2izrjNAFiam7ByUKOPPuecHefwO3Kdp2GR1J+4lYolCrPuq6aUti5Ar7ou1B2/CUWBAQ3dKF5YXfBk+q9nsC6Qh94+5T84VVjK3tzc3PD29sbJyYlChQpRpUoVoqPVxfLHjh3LsGHDqFChAgAFCxbMkHukU6ZMYenSpYSGhuLp6Ymnpyc7duwgODiYpk2baiqUzZgxgx49ejB+/HhMTEzYuHEjoK65O2nSJGrWrAmAi4sLv/zyi+b469ato1OnTlrVz3I6OTlC0iInR2QcOTkiY8nJEZIkSVKayKQrSZKUiWTSlSRJykQy6X5CG47f4ssVR3R2/rj4BLzHbaLt9zt0FoOUdfn5+WkWk8xsKdVkyA3k6IUcbMGei5Szs+JJWKSuQ5EkjQ/VZMgNck1PNzImjh7z91J77EZqjtnI1K2nAfXsskaTtlF3/GYaTtrKZf9nADx+Fk6lYWv5xu8oNUZvoPXM7Vx59Ix2s3ZQadhaluy/rDl2kT5LmLL1NLXGbqTud5uTnRChUilM3XqaBhO3UnvsRqYknj+luD7W3ZCXnLoTQpfa5TLkeNKnFRkZSZs2bXBzc6N8+fKMGTMGgL1791KtWjUqVqxI1apVuXDhAgD+/v6ULFmSgQMH4uzsjI+PDxcvXqRBgwaULFmSH3/8UXPst7UdXF1d8fDwSHYhTJVKxZgxY6hSpQpubm6MHj36g3F9jORqMqRmzbecItf0dA9ffUzBfKasHtIEgFcR6jGOlUsVYe/YtujpCS77P2PEmmPsG9cOgMf/hNO1djnm9PKm54K9jFxznG3DWxIVG0+VEevoXdcFEyMDElQKthbmHJ/SiT0XHjJ4+WEOTeiQ5PwbTtwC4MB37VGpFLrP36uZTpxcXO96/CycHvP3Jvu+xnesjo+rQ5LXFEVh+OpjfN+9tuzlZhP79u2jcOHC/PbbbwC8fPkSgGrVqnHy5En09PS4cOEC//vf/zh1Sr0Gn7+/P3369GHp0qW0bduWQYMGcfDgQSIjI3F0dOTzzz/HxMSEhIQE7OzsuHr1Ktu3b6d3796cO3cuyfnfLqV+5swZVCoVrVu3Zu/evURFRSUb17v8/f1p3bp1su9r5syZNGqUdAx7amoy5GS5Jum6OBRkwqZTjN3wF94udtQtbw/A07BIBv50kMDnbzDQEzx8GqbZx8bCTFP5q7xDQaJj4zE1MsDUyABLcxOehkXikFhe8bOa6vXGmnqUYMjyw0TEJF1k8OCVR1wLeM6By48AiIiN58GTMBpUKJZsXO9yKJSPo5M/S/V7XXnkOlUcbXC0tZBJN5uoUKECw4YNY+jQoTRo0ICGDRsCEBoaSrdu3Xj06BEGBgbcu3dPs0/RokU1q/m6u7sTFRWFqakppqamFCxYkNDQUIoXLw5Az549AWjVqhW9e/cmIiIiyfn37NnD5cuX2b17NwARERHcvXuXZs2aJRvXu4oXL56mpdxTU5MhJ8s1SbdE4fwcntiBo9cD2XjiNssOXmXj0OYMW32MHt4utKvmyOuoWEr/b7lmn/drMhi99328KvWD3hUFJnasTtNkVupNLq53pbWn+/edEE7fCWHzX7eJiYsnPCqWTj/s0jqulHWUKlWKCxcucODAAVatWsXChQvZvXs3X3zxBf3796dz5868fv0aCwsLzT7v12hIrmZDaimKwqxZs5LtsSYX17vS2tNNTU2GnCzXJN3gF28oYGZMS89SeJa2xnv8JgDCo2KxtVBXOFp19Hq6j7/5r9v09inP/kv+FCuUDzPjpIXD67k5sPLIdXxcHTAxMiDkZYSmuE5ycb0rrT3dnwY20Hx94mYQP+w8LxNuFhcYGIilpSXt27enRo0amim9YWFh2NnZAfDTTz+l+/hr1qxh4MCB7Nq1i5IlS2pV9WrSpAlLliyhcePGmJiYEBwcrEncycX1rrT2dP+rJkNOl2uS7o3A50zechqBugTi9K61ABjdtipDlh/G3NSIFsn0QlNDX08Q/OINtcduRF9fj4W+PlptutUuR/CLN9SfuBUhII+RIQt9fXj0T3iycUm5y9WrVxk5cuTbaa4sWLAAUNc/6N27N/ny5aNdu3bpOra+vj4BAQG4ublhYGCguX/7rr59+xIYGEjlypURQmBmZoafnx8PHz5MNq6P8V81GXI6WXshA6R1SfesTtZeyDhZofZCTlqiXdZekCRJktJEJt0MkJN6uVLOk1N6uTmFTLofMPO3M8zZce6/G35CyU3lfR0VS5cfd+M5Yh31JmzhTnDyS1eHvHxD82m/UWXEOlpO/53QVxHJtpOynwkTJuhsxYWoqCgaNGhAgQIFtAqQh4eH06JFCxwdHalcuTI3b95M9hhBQUHUrl2bMmXK4O3tTUhISGaEniXIpJvFvZ3K+/5rzvZWnJ3ZlZFtqjBs9bFk9524+RQdapThzMyutK5Smqlb/86MkKUc7u0Mt7Vr12pt+/7773F1deXu3btMmjSJL75I/lnLiBEj6NatG3fu3KFjx46aGXC5Qa5JutO3/c3cXf8W1dh+5h79lx4A1Eut15+4hVpjNzLwpwPEJK4Q8a5Bvxxi88nbmu89h6/l8bNwAK4H/EPrmdvx+W4Lzab+muw04PRIaSrvznP36Zb4WoMKxbgfGsaLN9oz2f649IjPaqgnbXxWsyx7Lz7MkLikjDVu3DimT5+u+X7Lli106dIFUC+77unpiaurK926dUu2RkGvXr2SJMDSpUvj7+8PwJUrV/Dx8aFSpUrUrFkz2SnAaWVoaEjdunUxN9dep2/btm2aIjpNmzblzp07PH+u/fOwa9cuevToAagnbmzfvv2j48oucs2QsfbVy9Bn8X6+al4JgG2n72oSV0pLradGXHwCQ1f+id/gRthYmHPhwRO+WnmEP8a3T9IuI6fyBr+MoKjlvx94W0szgl+80bwHgBdvosljbIiJkfq/2MzYEEN9PcIjY8iXxxgp6+jatSsdOnRg1KhRAKxfv16TuFJadj014uLi6N+/P9u2baNo0aKcPXsWX19f/v476V88aZ3c8CGBgYHY2/87q9LOzo7AwEDNewB4/vw5ZmZmmmm/ZmZmGBoaasbt5nS5Juk62lpgqK/P9YB/sLPMy8WHT1n+hXpKY0pLrafGvdBX3Ap+Qecf/p2l8zJCuzeS2VN5dT1MSUo9JycnjIyMuHLlCg4ODpw9e5bNm9Xr76W07Hpq3L59m+vXr9OsWTPNay9eaN//T+vkho+V2z+buSbpArSr5si2U3cpWSQ/jSsWx9BA/4NLrb9LX18vyYfl7SKVigIlUpFQM3Iqr62FGUEv3mgWpwx+EYGNRdIZRpbmJkTGxBEdG4+JkQERMXHExqtkLzeL6tKlC+vXr8fR0ZGWLVtiaGj4wWXX32VgYJAkGb9dsFJRFEqVKvWfCTUje7p2dnYEBARQsqR6olFgYKBmuu9bVlZWREREEB0djYmJCREREcTGxuaKXi7ksqTbtpojzab+ikOhfIxqqy4U8qGl1t9VrGBeLvs/4zMvJ87cDdGMBHC0KcCb6DiO3QiktrMdiqJw9fE/uBUrlGT/jJzK27xSSdYeu8nY9tU4cPkRJYrkxyqvaZL9hRA0qFCMTSdv09PbhU0nbtO4YvFUn1/KXJ07d8bLy4sSJUowefJk4MPLrr+rRIkSnD9/nh49enDy5EmCg4MBdQ/69evXHDp0iHr16qEoCpcuXaJixYpJ9s/Inm7btm1ZtmwZ06ZNY8+ePZQuXZqCBQsmaSOEoFmzZqxevZr+/fuzatUqWrZsmSHnzw5yVdK1sTCjWKF8PHoWTpXS1sCHl1p/V3dvZ3rM30utsRupVsYGh4Lq6mKGBvqsHtKEUeuOM27DX8QlqGheqaRW0s1Ig5tWZMBPB/EcsQ5zE0OW9P932I73uE1sGNocGwszxneoxoCfDrJw7yWK5M/DL583+MBRJV2ytbWlZMmSPHjwgBo1agAfXnb9Xf369aN169a4urpSq1YtTWUxQ0NDfv/9d4YMGcLQoUOJi4ujbdu2Wkk3Pdzc3AgJCeH169fY2dkxY8YMunXrxvDhw+natSuOjo7kzZuXNWvWaPZxd3dnz5492NraMmPGDLp06cKsWbOwsbFhw4YNHx1TdiGnAUta5DTgjJMVpgHnJHIasCRJkpQmMulKkiRlIpl0JUmSMpFMupIkSZlIJl1JkqRMlCNGL5gaGYRGxyUU0XUcOYWJof6TqNh4a13HkROYmpqGRkdHy89mBjExMXkSFRWVrT+bOSLpfmpCiOLAeaCCoiiBOoqhAbAEcFEURXuesZRrCSG2AycVRZmpo/MbAdeALxVFSX7apaQhby+kzvfAXF0lXABFUQ4AN4AvdRWDlPUk/jIuD8zVVQyKosQCXwM/CiEM/6t9bid7uv9BCFEHWA04KYoSpeNYHIFTQHlFUUJ1GYuke0IIA+AyMEZRlN91HIsA9gL7FEXR2S+A7EAm3Q8QQuijvq0wTVGUzbqOB0AI8T1QUFGUPrqORdItIcQgoDXQICtMexNClAOOAc6KojzTdTxZlUy6HyCE6A90A+pkhQ81gBAiH3AbaKkoylldxyPphhDCCrgJ+CiKck3X8bwlhJgLmCiKMlDXsWRVMummQAhRALgFNFEU5aKu43mXEKIP4At4ZZVfBlLmEkIsBFAUZZCuY3mXEMIC9c9NI0VRMq9IbzYik24KhBA/AOaKovTXdSzvE0LoAWeBOYqirNd1PFLmEkKUBw4D5RRFyZi1oTKQEGIg0AmoKzsF2mTSTYYQoixwAvXwrKe6jic5QoiawAbUD/jkMr+5ROIDqwPAdkVRFug6nuQkPgu5AExSFGWbruPJauSQseT9AEzPqgkXQFGUE6h/MQzXdSxSpmoJ2ABLdR1IShRFSQC+AmYLIUz/q31uI3u67xFCNAV+BFwTxx9mWUIIB+Ai4KEoyiNdxyN9WkIIY9RjtQcmjtvO0oQQ24ALiqJM1XUsWYlMuu9InFlzBfhGUZTd/9U+KxBCfId6iE7q1wKSsiUhxAighqIorXQdS2oIIUqifvbgpihKkK7jySpk0n2HEOJroCHQNLs8ABBC5EH9tLiboijHdB2P9GkIIWyAq0B1RVHu6jqe1BJCTAUcFEXprutYsgqZdBMJIQqh/tOttqIoN3UdT1oIITqhvrfrmXg/TcphhBArgH8URclW9/CFEOaoOwXtFUU5ret4sgKZdBMJIZYCUYqifK3rWNIq8Yn2ccBPUZRluo5HylhCCE9gB1BWUZRwXceTVkKI7sAg1L101X+1z+lk0gWEEO7APtTjHl/qOp70EEJUAnaj/sEM03U8UsZI/IX6F7BMUZQVuo4nPRLHlZ8EFiuKslrX8eharh0yJoSwF0I0SfxQzwUmZNeEC6AoynlgFzAOQAjRM/Fpt5QNCSF8E5NVZ8AI8NNtROmX2Lv9EpguhMgrhKgghKiq67h0Jdf2dIUQPVA/NPsddaLyyO73Q4UQRYDrQA3Uf462yW73pyU1IUQUYI96SGAnRVH+0nFIH00IsRoIBP5B/XDtKx2HpBO5tqcL5AdeA7NQD+RunThvPFtKnEVXFpgJzAFeAQV0GpSULol/oegDg1FPgHkhhKil26jSTwihJ4ToBkwA+gMGqH/+cqXcnHQLAOVQV2oaA4xE/UHPrkyAtYAT4Ewu/2Bnc287BIOAx6jLJRbUaUQfrwXqZw5bgDbk4g5Bbk66RQEvoBrquezVFUX5R7chpZ+iKJdRryAQD+QDXAFLnQYlpVd+wByIASoClRVF+U23IaWfoiiqxMk741EnXHeguE6D0qHcnHTLA6GoZ/jMVBQlXtcBfSxFUcIVRRmAusJTAurEK2U/hVD/pTIFdYnEHDHFW1GULag/k+dQd3pypdz8IM0QiM8uM8/SKnEpl4Sc+v5yOiGEoaIocbqO41PJ6e/vQ3Jt0pUkSdKF3Hx7QZIkKdMZpHUHE0O90Jh4pcinCCanMTYQT6LjVNYpbTc1NgqNjo2T1zIVTIwMn0TFxKZ4LQFMTUxCo2Ni5PVMBRNj4ydR0dEfvp6mpqHR0dHyeqaCiYnJk6ioqA9ez7fSfHtBCKEETayersBym6LfnUJRFJHSdiGEEn5UlkpIjXzevh+8lqC+ntH+FzIrpGzNpLhHqq6nvP2YOkKI/7yeb8nbC5IkSZlIJl1JkqRMJJOuJElSJsqVSffWk0gaL72C17yL9Nlwi4iY5OvcnHwYRt2Fl/Cad4Fvt98nQSXvbyXnxoMgavefhHvX0XQes5A3kdHJtjt+8RZVeo2nQpdRDPrej4SEXF9aVcv12/eo3rwLLt6t6NBvKG8iIpNt9+epc1Rs0B7nOi0ZOGISCQnZulbTJ3Pt2jUqVaqEo6MjrVu35s2bN8m2O3r0KC4uLpQuXRpfX99Pej1zZdIduesBo+o78NeXFSlpZcpPJ4O12qhUCsN23OenjmX460sPXscksO3KMx1Em/V99cMavuvXjkvrplHavggLNv+h1UalUjFo1ipWTxjI5fXTeR0ZzcYDp3QQbdY2aMw0Jg0fzPWj23Es6cDcX9ZotVGpVHw+chLrF3/PjT938PpNBOt/26ODaLO+gQMHMn36dO7evUuZMmWYM2eOVhuVSoWvry9btmzh3r17hIeHs3bt2k8W0ydNug4TTzHr8GPqL75Mo6VXuB4aQa/1t/Cad5GJ+/w17cbufkjTn65Qb9ElBm+7S0y8ugcUFZfAiJ0PaPazetvKv0M+OqZnb2IJCouhTml1vY1OHoXZc/OFVrtLwW8okteIMoXzANDZozB7bmi3y0wWPv2ZsuJ3avSdQK1+k7h6L4DPRi/AvetoRi/epGn37bz11BkwhWq9v8N3yi/ExKon/kTFxPLVnDV4D1Rv++nXwx8d09MXYQQ+fUE9TxcAejStxY5j57Xanb/lj03BAjgVtwWge9Oa7Dimu5EGZqU8mfjDEjwbf0a1Zl24cuMO7Xy/wsW7FSOm/KBp9/V3M/Fq2Y1KjTrS66sxxMSoF4iOio5m0Oip1GzVnUqNOrJk1caPjunJs+cEBIfSoLZ6dFCvjq35fd8hrXbnLl/HpkghyjmWTGzXKtl2mcnAwIDx48dToUIFPDw8uHz5Mi1btsTR0ZFvvvlG027w4MF4enri6upKt27diImJASAqKoqBAwdSpUoVXF1dWbhw4UfH9OTJEx4/fkzDhg0B6Nu3L9u2bdNqd/bsWWxtbXF2dv5gu4yS5nG6aZGgAqciZgzzcWDCPn/6b7rNrn6u5DHSp+b8i/Spao29hQlD69phmccQgHF7HrL54jO6exZh4fEgXG3MmNmiJDHxKlovv4ZXifyaRPjWkF/vcvOJ9p9hnvZ5mda8ZJLXQsJjsc33b23vovmNCA6L0do3te0yU4JKhUtJO8b2ac2oRZvoNn4xR5aOwczEmIrdxjCgTT2K2RRkVK+WWOU3B2DY/PWs23eSPi3rMGfdHiqUcWDuN92JiY2j4aAZ1PFw0iTCt/pPW871+4Fa56/qWpofvuqa5LWgZy8pWvjfiph2RSwJeqpdCz742UuKFv63/o59EUuCnurul1hCQgLly5bmu6GfM3zyHDp9/i0ntq/BzNQUl7qt+bxnJ4rb2zL2qwFYWah/QQ+d8D2rt+6gX9f2fL94Je7lnVg4TZ2I67bvjXeNKppE+FafoeO4dlN7HcnqlSswb/KoJK8FhT7BzubfYbH2Ra0JDH6itW9Q6FPsbKz/s11mSkhIwNXVlUmTJjF06FDatWvHmTNnMDMzw9HRkcGDB1O8eHEmTJiAlZUVAEOGDMHPz48BAwYwffp0PDw8WLp0KTExMXh5eeHj46NJhG/16NGDK1euaJ3fy8uLRYsWJXktMDAQe3t7zfcODg4EBARo7ZvadhnlkyZdIaCJk/oHzcXajKevY7FITK6lC5oS8CoGewsT/rj1ktVnQ4mJVxEek4AqcWzg4buviI5TsepsKABvYhK4/zxKK+nOb+uY6phSO+wwKw5PFELQomZFAFxL2xP6PAzLfOrk6uhgzePQfyhmU5A9f11i2fajxMTGER4RhSrxXvSB01eJio1j2e9HAXgdGcXdgFCtpPvz6L6pjin11zNrXVAhBK0a1QXAzbksIU//wbKAuhJm2VLFeRQYTHF7W3YeOMova7cSHRNL2Os3qFTqv8L2HzlBVHQMP6/ZAkD4mwju3PfXSrorfpic6piy67UE9fVs06YNAO7u7oSEhGBpqf7Zd3Jywt/fn+LFi7N9+3aWLFlCdHQ0YWFhmuu5Z88eoqKiWLx4MQDh4eHcvn1bK+muXp361X5Se50y+3p+0qSrJ8BAX2i+NjLQS7ItXqUQ8DKaOUcD2DfADSszQ1acDuFGYq9VUWBBO0fK25h98Dxp6ena5DMiOPzfHmtQWCw2+Yy09rXNn1w73a5+oycEBgb6mq+NDQ2SbItPUPEo5B+m++3g2M/jKFggL0t/PcS1e+rf2goKy8b44ubo8MHzpKWnW7SQRZKebeCTF9gW0q4FX7Rw0p5tQArtMouenh4GBgaJXwuMjf79DKivZQL+AcFMmfszp3auo5CVBYv9NnLl5h1A/YPqN3cqFVzKfvA8aenpFrUuTGDIvz3WgKBQitpoTwizsylCYEjoe+0Kp+JdfzpJr6cexsbGSbbFx8fj7+/PhAkTOH/+PIUKFWLBggVcvnwZUF/PdevW4e7u/sHzpKWna2dnl6TH+vjxY+zs7LT2tbe3T1W7jPJJk25qvI5JwMRAj/wmBkTFqh9WlSuiTrJ1HQuw/HQIs1uVQl9P8OB5FIXMDMlrkjTstPR0C+c1wjafMX/ee0Wd0gXYeOEpTcpZabWrYGtOSHgsd55GUqZwHjZceEpT56xfnvZ1ZBQmxoYUMM9DZHQMG/84RfmS6g9Q/SquLNl2kIXDeqGvr8e9wCcUtshHPjPTJMdIS0+3iFV+iha24NDZ69TzdGH1nuO0qO2h1c6jbHGCn73kln8wTsVtWbPnBC2TaZeVvH7zBlMTYyzy5yUyKor1v+2mvJP6s9bQ24uFK9ezdOZ49PX1uffwMYULWpIvr3mSY6Slp2tduCB2NkU4cOwUDWpXx2/z75re+LsquTkTFPKUm3cfUM6xJH6bt9Oqkc/HvdlMEB4ejqmpKRYWFkRGRrJmzRrc3NwAaNKkCfPmzWPZsmXo6+tz9+5dihQpQr58+ZIcIy09XWtra+zt7fnjjz9o2LAhy5cvp23btlrtKleuTGBgIDdu3MDZ2TnFdhlF56MXnK3NqF48H3UWXqTjqhu4F/33Q/tlbTvMjPRpsOQyPosuMXzHA+ISPv5PgenNSzD1wCO85l3k3j9RDPRS/3l9OegN3deqlxTT1xPMalmK/pvvUGPuBcyM9GjnVuijz/2plS9lTy33slTqMZYWQ+dQyamEZtvw7s0xMzWhRt8JVO01niGzVhEX9/FlhH/8uhvf/bQV966jufM4lCGfNQLgwi1/2o2YC4C+vh4LhvWk+3dLcOsyCjNTYzo1yNrTyV3LlaF21Uq41WtLky4DqVzBRbNt1CBfzM3y4NmkEx4NO/D5yMnExn18pcIFU0YxdsZ8XLxbcfu+P1/37wHA+Ss3aNVrMAD6+vosmTmOzp8Po1ztlpjlMaVr22Yffe5Pzc3NDW9vb5ycnKhXrx5VqlTRbBs7dizm5uZUqFCB8uXL069fP2JjYz/6nEuWLGHEiBE4Ojpy69Ytvv32WwDOnTtH06ZNAfX1XLZsGe3bt6dUqVKYm5vTvXv3jz53SmTthU9I1l7IOLL2QsaStRcylqy9IEmSlEXJpCtJkpSJsmXS3XTxKd9uv5/p5z12/xVNfrqCz6JL1F98me3Xsu06lkms2/sXg773y/TzHj53nTr9J1O113hq9J3AtsNnMj2GT2H1lh0MHDEp088bFR1N026fU8S1Nk26Dsz0838Kfn5++Pr6Zvp5/f39MTY2xt3dHXd3d6pWrZphx9b56IXsxDKPIcs7lcU2vzGh4bE0WnqFmiXyY2VmqOvQsiWr/HlZP+V/FC1sScg/r6jZbyJ1PMpRsEBeXYeWLRno6zP8iz5ERkWxYMV6XYeT7dnb23Pp0qUMP+5HJ92o2AQGbbvLo5cxqBSFhmUtGVnfgcN3X/LD0UBi41UY6esxvXkJXG3NCXgZTcdVN6hdqgB/PwqnkLkh3zUqzpQ/HvHoZTS9q1jTv4Z6NIHDxFN87lWUg7dfYKCvx9w2pTTDyd5SqRS+PxzA8QeviIlXqFfGglH1HVKM62O8O17YOp8RhcwNefomNkOTbmR0DL5TlvEw+CkqlUKzmu6M923LH39fZYbfTmLj4jA0NODHr7vhXqYYj0L+ocXQ2fhUduGvK3coYpmfqV90ZPzSLTwMfkb/tj4M6qCeBmnh05+vOjdm78nLGBros3RUH1xKJh2PqFKpmLLidw6fu0FMbByNq1fgu35tU4zrY1R4Z7ywTcECFLbIx5MXYRmadCOjouj15VgePA5ApVJo3qAOk4YNYv+Rv5g67ydiYuMwMjRk/tRRVCxfDv+AYBp3GUD9WtU4ceYCRQpZMXPMUEbPmMeDR4F80fMzhvh2A9RTiYcO6MGeQ8cxNDBg2ZyJmiFlb6lUKibMWczhE38THRNDE59aTB4+OMW4PoahoSHeNTz589S5jzpOSiIjI+natSv3799HpVLRqlUrpk6dyt69e5k4cSIxMTEYGRmxZMkSPDw88Pf3x8fHh4YNG3Ls2DGsra2ZM2cOw4cP5/79+wwePJivv/4aUE8jHj58ODt37sTQ0JBVq1bh6pp0MWuVSsW4ceM4cOAA0dHRNG/enGnTpqUYV1b10Un3QnuGiAAAFw1JREFUyL1XWJkZsryzEwCvotRDkDzs8rKjb3n09ARXg98wevdDdvZTX8SAVzF0qliImS1K4rvxNmN2P2Rjz3JExamoNf8iPTytMTHUI0Glnsxw6H/u7L/1gqG/32fvALck5998SV2EZnd/N1QqhT4bb3P47kui41TJxvWugJfR9Nl4O9n3NaZBMbwT6zMk5+zjcCJjE3AsmCfFNulx8Mw1Clmoe4AAL19HAODpXJKDi0aip6fHpTuP+GbuOg4tHg3Ao9DndGvqxdxvutN13CK+nbeOHXO+ITI6lordRuPbsi4mxoYkqFTYFrLg9MqJ7D5xkS9mrOTPn8clOf+6fScBOLp0LCqVis5jF/HH31eJjolNNq53PQr5hy5jF2m9DjBxQDvqVymf4vs+ffUuEdGxlHWwSeMV+7A//jxJISsLNv+sLnTyMiwcgCoe/2/vzOOirPY//p6NGURAVtmVxdRS1EQzt9xQXEIuucTy0tCiXCIv3TRNk9JrpJWVmWbmvu+W+5LdcsncRXNDRfZFJECYYZ3fH0+OIIOxxcXfPe/Xa/54mOec5/ucYb7Pd84538+3LT9tW4FcLufcpStMmhHNf7avlO4jMZnRI4by1Zz3GPn620ya+TF71y4iX6ujTa8AwkOHo9GoKSkpwcWxKWf2b+KHAz8R/k4Ux39YW+76q7Z8D8DRnaspLS1leHgk+48cQ1ugM2pXWeISkhkRHmn0vv79bgS+L3Stm0GqIvv27cPe3p7t27cDkJUlJcV06dKF48ePI5fLOXv2LBMmTODECUnMKC4ujjFjxrB48WICAwOZOHEihw4dIj8/nxYtWjBu3Dg0Go00li4uxMTEsHPnTsLCwjh9uvzDY8WKFQD89ttvlJaWEhAQwN69e9FqtUbtKktcXBwBAQFG7+vjjz9mwIABFf6elJTEs88+i0qlIiIigpCQECOtq0+tne7TDmbMPnCHqH1x9PS05AVPyVFl3C/kza13SMouQCGXEXfvodyfg7kJHVykaOYZh0boikoxVSkwVSmwaqQi434hrlYaAEa0l/bGDmhlTeSOWPILy0uuHb6Rxe+p+Ry+IQ10fmEptzN19H3KyqhdZXG10nBwXLtq33PSHwVEbIvly0AvQ8ZdXdHG05Xpi7cwdeFGevs8TV8faW9o+r1sXvv3UhJSM1EqFNxKSje0cbJtgk9rKfOurZcbuoJCTNUmmKpNsLE0J+1eNs0cbQEIHiB9UQd378C4j5eTpy2vJ3Hg1xhibiaw/0QMAHm6Am4mpjGgi7dRu8rSzNGWY9/NrPY9J6RlEj7nO5ZMG2vIuKsr2rZ+iqlzvmDyrE/p270L/Xp2ASAt4y5hk6YTn5SCUqHg5p2HGUlODvZ0ai89ILyfbolWV4CpRoOpRoONdRNSMzJp7ir9Ggt96UUAXuzfi/B3osjL15a7/v4jx7h45Tr7fjwKQJ5WS2xcPH59uhu1qyzNXZ34bW/thXTqinbt2vHOO+8QGRmJr6+vQUgmNTWV0NBQ7ty5g1KpJDY21tDG2dnZsB+3ffv2aLVaTE1NMTU1xdbWltTUVJo3bw7A6NGjARg6dChhYWHk5ZV/sO/Zs4cLFy6we/duAPLy8rhx4waDBw82aldZmjdvXq2pAkdHR+Lj47GzsyMhIQFfX1/c3d3p2rX2D7paO93m1hr2veHNzzez2Xw+g+UnU1kd2pqpu24T6tOUgLa23C8o4enoh4skauVDRyWTyYymB1cZPczo3wy/1hWzxYzZVZaaRLp37xcRsuYKM/o3o5ObhZGWtcPD2Z5flszgyOnfWbfvOEu2/8iW6LeInL+WV17syfC+z5Gbr8NtSIShjckj6cCPHhdXQxtUj57ZbwxnSI8OFd4zZldZahLpZmTlEDj5c2aPG06XtlXPLKwqns1c+XXXWg4fPcmarT+waNVGdiz/kojp0YwNCmTkUD9y7+fh0K6XoY3a5OF0kVwuL38sk1NSUvWEEr1ez0dTJ+FvJLPMmF1laWiRrqenJ2fPnuXgwYOsXLmSr776it27dzN+/HjCw8MJCgoiNzcXK6uH6d2PpgMbSw+uKnq9nnnz5hmNWI3ZVZbqRrpqtRo7Oyngc3V1JSAggBMnTjQMp5ucXYCVqZIhz9jg42qO7yIplzq3oMSgabDmdM0VkLZcyGBUJwcOXsvCzUpDI5PykVDvFk1YdSqVXl5N0KjkpOYUGhy3MbvKUt1IN1dXTMiaK4zr5sSgpyumDtcFSen3sLIwI6CXD8+18aLr2CgAcvK0OP+pVbD8+//UuP8NB04wdmgv9h6/gLujHWam5fUkfDu3Yen3P9Gvcxs0ahUpd/8wOG5jdpWlupFuTp6WwMmf89bLA/Dv2bHG9/Q4ElPSsG5iQeCgfnTp2I7OA0dK1869b9ArWLqu5jJ+67bt5rXQYew5/DPubs6YNSqfUt2/VzeWrNlM/xe6otGoSU7LMIynMbvK0tAi3cTERKytrRk2bBhdu3alXTvpu5OdnW3QKvjmm29q3P/q1at544032LVrFx4eHpiZlV+/GThwIIsWLcLPzw+NRkNycrLBcRuzqyzVjXTT09OxtrZGqVSSnZ3N/v37mTt3bo3vrSy1drpX0/OZczAemUwSqJk9SEo7ndzHlcgdsTRWKxlkJAqtCgo5JGcX0u/rCyjkMuYHeFY4J+hZe1JyChm05CIywNREwecBXsT/oTNqV21YdjKV2Ix8lv6awtJfJW3fOYM96ORWdws/l28nEbVkKzJk6NEzLyIYgOljAxgXvRwLM9MaaxYo5HKSMu7x/JiZKBUKFr0bVuGcUYN7kJSRxQuvz0Imk9FIo2bxu2HEpd41aldt+GbbYa7dSWHRlsMs2iLpwX72zxCea+NV674fcPlqLNM//vJBxhCfRU0BIOpf4wl/JwqLxo0JGFgz3QKFQkFCSio+fiNQKpR8+0lUhXPCRgaQlJJGV/9QZDIZZqYavv3kA+ISko3aVVt8/EaQmn6X3Pv5eHbxY9aUNwn+R92kCMfExPDuu+8abF6wYAEAs2fPJiwsDAsLC1566aUa9a1QKEhISMDb2xulUmmYvy3L2LFjSUxMxMfHRxpLMzNWrFjB7du3jdpVG44ePcr770u6GiUlJYSFheHr61vrfqGBpwG7fXCC+JlPbspxQ0sDtuoTTtaPS+rtenVJQ0wDNvPsRN7NU/V2vbqkoaUBK5XKak01NDREGrBAIBA0UBq0032So9yGyJMa5TZUntQotyHyJEe51aVBO12BQCD4/8Z/JQ340yMJKOQyJr3w96mzV0ZClo6eC87jZSetMqsVcnaFS0kbubpiJm6NJfauFguNgi8DvWhhVzH5ISWngAlbbpB+vwgHcxMWDmtBU/OK1SfqgznLd0rpn6OG1Pu141IyGDVzESUlegqLi/Hv2ZEZY6VtOTl5Wl6d/S3X41OxNDNlyXtjadnMqUIfyRlZjJm1hLR7OTjaWLLs/XAcbCpPSvm7mTV/MUqlkqlv1n++/6FffuX9uQvQFRSikMuZPGEMw1+UtjLl5N7nlUnvce1mHJbmjVk2fxatvDwq9JGUms6oiKmkZWTiaG/HqgVzcLT/7+lAR0VFoVQqmT59er1fW6vV4u/vz6lTp/Dx8eHQoUOG93JycggJCeHq1atYWlqyevVqWrduXaGPpKQkgoKCSE1NxcnJifXr1+PoWLsEnv/JSNfJ0oSD49pxcFw7g8MF+PpYMq2aNuLYWx34V29Xpu66bbT9nIPxBHrbcTSiA0OesSH6UHx9md6gcLRpwoEFUzn23UyOLZ3J4VOX+OXcVQA+X7+PZzxcOL92DtPGDCVy/lqjfbz/zRZG+nbh3Jp/84/enfjg2231eQsNClurJmxa8hlnD2xm58qvePuDeWRkSkk/n36zkmdaenH5p528HzmOiOnRRvt4L/oLggIGcenIDoYN8eX9ubWvqvukolQqmTZtmtFy6nPnzqVt27bcuHGDDz/8kPHjxxvtY8qUKYSGhnL9+nVGjBjBtGnTam1XrZ3u3MPxLPg5yXD8w+VMJmyR6khVVlq9LJO2x7L1QobhuNsXZ0nIkrLXfk/NY/iKy/gtvkjAd5e4klYx9bQu2fP7PYKflfZu9n3KituZWu7lV6wGcOh6FsPaSdHDiPZ2HLhWN1VtZ323g0/X7jEcb//pNGNmSfOwlZVVL8sbHy1jw4EThuN2wVO5kyIpoV26mcCQf35Cz/AP6T8xmsu3KtZAqy5qExUatZQ4UFRcQnFxCTKZtID7/c9nGDW4BwADungTm5hGZvb9Cn3sP3GRoP7ShvPgAV3ZfazuBEaiPv2auQuXGY637j7IqAjpS1NZafWyvPr2TNZtf7jJ/ukX/IlLSAYg5sp1BgSF8/yQYHoPG8OlqxXroFWX9m1aGaoBOzW1w97WmrQM6fPbsfcwYS9LhR/9encn9vYdMrP+qNDH3sO/EBoo/eoJfelFdh2s+Z7uR5kxYwYfffSR4Xjz5s0EB0tbBysrrV6WV155pZwD9PLyIi4uDoCLFy/Sp08fOnbsSPfu3YmJiam1vSqVit69e9O4ceMK723dutWgXjZo0CCuX79OZmZmhfN27drFqFFS9Y7Ro0ezc+fOWttV6+mFQG87Xt90jTd7OgOw42IGQR2lf5zKSqtXhaKSUib/cItvRz6Fo4Wa80n3eWfnrXKRKdQsq+yBQphKLmNMFwcC/yzDk5JTgJPlw2kCRws1KTmFhnsAuJdfRCOVHI1Kel41MlGglMvJ0RVjoandcI7s9xyjohbzdohURmTzoZMGx1VZWfWqUFRcTMQnq1nz4Tic7Kw4c/U2E+et5Mii98qdV5OMsszs+7wY+Qk3E9N5LaA33dtLhRqTM7JwKVOa3cnOiuSMLMM9PGjbyFRtcNxmpmpUSgXZ9/OxbFx7TYugoQMJnjCFyRPGALBx5z7CXpamPyorrV4VioqKmDB1NusXf4Kzgz2nL1xm3JRZ/LKzfP2u2mSUHT99nrx8Ha28pP3lSanpuJYpUuns0JSklHTDPQBkZv2BWSNTNBop4cWskSkqlZLsnFwsLWq/lzwkJIThw4czdapUUHPdunUGx1VZafWqUFRURHh4OFu3bsXZ2ZlTp07x6quvcvLkyXLn1UQ/oTIeLbvu4uJCYmKi4R4AMjMzMTMzQ6ORJAnMzMxQqVRkZ2djaWlZ5Ws9Sq2drpedKSqFnN9T83C2VHM+OY/FIySDKiutXhVu3tVxPT2fUWuvGv5mTLSmulll9uYm/BbZERszFUnZBQSt+h3XJpqqJzj8jdsWn2rmiIlKwaWbCbjY23D2ahwro6R/3MrKqleFG/FpXI1LYvi7D9NMjQnW1EQ7wcayMce/i+LuH7kMn/olV24n0drduWqN/+Y9oC293DFRKYm5ch1XJ0fOXLzM2oXSz/LKSqtXheu37vD7jVv8I+xhKvY9I4I1Nc0oi09KYcw/Z7Bs/ixDhd2q8HfvqW3VqhUmJiZcvHgRNzc3Tp06xaZNmwAqLa1eFa5du8bly5cZPPhhEse9exV/PVY3q6y2/F3jWScLaQFtbdkRcxd3aw39W1qhUsgfW1q9nAFyGWX9h65YOtCjp5n1XzvU6ka6aqUc9Z9aD86WavxaWXMmIZdObuY4WqhJzi6kmbX0ZEvJKcDxkQUyq0ZK8otK0RWVolHJyS8soaiktNZR7gOG932OzYdO4unSlIHd2qFSKh9bVr0sSoW83IOtoFB6SOnR4+5k/5cOtTYqYbZNzOnm/RSHT1+mtbszTnZWJKZn4e4k/YpIzsjCybb8Z2Ft2Zh8bQG6giI0ahV52gKKikrqJMp9wMihA9m4cx+e7m4M7vcCKpXqsaXVy6JUKso93B5MQej1ejzcXP7SodYk0k2/ew//0ROJfm8SXX0eliN3drAnISUNDzdp8TkpNQ0nh/ILZDZWTcjL16LTFaDRqMnL11JYWFQnUe4DgoODWbduHS1atMDf318az8eUVi+LUqks54x1OmkaUa/X4+np+ZcOtS4j3Qfl2T08pMXIxMREnJ3LBws2Njbk5eWh0+nQaDTk5eVRWFhYqygX6mghLaCtLd9fymRbzF0CvSU1K2Ol1Y3h2kRNTLI013cqPpe0XOkf28vWlLyCEn65lQ1IH8yllIrR2YNI19irMsGa4j8rCufoivkp9g+edpC+5ANbW7PurKTedfh6Fs2tNVg/opUrk8no28KKLX/OQ286n4Fvy7orzT6s73NsO3KaTYdOMrKfpFZvrKy6MZo52nL++h0ATl6KJSVTmvN7ys2BXK2On85IlY71ej0XblRc/HsQ6Rp7GXO4ien30P7piHLzdfzn7BVaN5f+cf17Psuq3b8AsP/Xi3g422PziE6uTCaj//PerD8gyUmu23+cgd2qr/r2OEb4+7F51wE27NjDywEDJVuNlFY3RnNXJ87FSGN24swFktOkz7ylZ3Ny8/L58Zj081ev13P+0lWj7X/bu8Hoy5jDzcm9j//oifwzfBQBfn3LvTfUrw/LN0jShfuOHMWjmSu21lblzpHJZPj16cGabbsAWLP1Bwb3q9oUVFUJCgpi48aNrF271iB1aKy0ujHc3d05c+YMAMePHyc5WZofb9WqFbm5uRw+LKWC6/V6zp07V6H9g0jX2Ks6DhcgMDCQpUulbNA9e/bg5eWFra1tuXNkMhmDBw82lH1fuXIl/v7+1bqOMeokPHOwMMHNSk18VgE+rtIXq2xpdetGKto7N6aguGK4HtKxKWM2XKXvwvN0bmaBaxNpPkqlkPNdUEtm7Injg31xFJfqGdjaupyQeE34LT6HT44kIJfJKNXrGdHenp5/yj6O7+7ExK036PbFORqrpS1jD/BddIHVIa1xsDBhqq8bE7fcYNGxZJqaq1g4rO7UsRxtm9DcyZa45LsGDYKyZdVtm5jTsZW70YW0V4b0JGj6QrqEzeR57xY0c5Dmp1RKJetnT2Dyl+uZ9vVGiopLeLHHs+VExGvCldvJzFi8GblcRklJKSF+3ejbSZJ8fOtlP16dvZT2IdMwb6RhybSxhnbdxn7Alo/fwtG2CR+Ev8TYWd/yxYb9ONhYsmxGeK1sehSnpna4uzlzOz6J5ztKDr1saXU7ayt82j2DzshC2piXAxkRHknHASPo1qkDzVykLW8qlYrNSz4lMmoeU2Z9RlFxMUP9+tC+Tata2fr1yg1cjb3NwuXrWbh8PQBfzJ7K8x3b8fbro3ll0ns802so5mZmLJs/y9Cu88CX2bFiAU5N7Zg95U1GvzWN+UtW4WBvy6ovP6rscjXCyckJDw8Pbt26ZVDcKlta3c7Ojs6dOxui2LK89tprBAQE0LZtW3r06GGQdFSpVOzYsYOIiAgiIyMpKioiMDCQDh0qKt1VF29vb1JSUsjNzcXFxYXo6GhCQ0OZPHkyISEhtGjRAnNz83IPivbt27Nnzx6cnJyIjo4mODiYefPm4ejoyPr162ttU4PWXnjSaWjaC08yDVF74UmmoWkvPOkI7QWBQCBooAinKxAIBPWIcLoCgUBQjwinKxAIBPVItRfSNCp5akGxvmppZf/jqJWyNF1RqUNl75uqTVJ1hUViLKuAxkSVpi0orHQsAUw1mlRdQYEYzyqgUavTtDrd48fT1DRVp9OJ8awCGo0mTavVPnY8H1BtpysQCASCmiOmFwQCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAeEU5XIBAI6hHhdAUCgaAe+T+z54ZuMUi99QAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "_ = plot_tree(tree, filled=True, proportion=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Explain for the example [x=150, y=75, z=200]" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "import sklearn" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([100., 300., -2., -2., 200., -2., -2.])" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.threshold" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0, 1, -2, -2, 0, -2, -2])" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.feature" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 1, 2, -1, -1, 5, -1, -1])" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.children_left" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 4, 3, -1, -1, 6, -1, -1])" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.children_right" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 1, 2, -1, -1, 5, -1, -1])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.children_left" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "from collections import OrderedDict" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [], "source": [ "features = [[1, 75], [2, 200], [0, 150]]" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "[[1, 75], [2, 200]]" ], "text/plain": [ "[[1, 75], [2, 200]]" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "features[:2]" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([10, 4, 2, 2, 6, 1, 5])" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.tree_.n_node_samples" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def decision_path(i):\n", " \"\"\"\n", " i: index of features\n", " \"\"\"\n", " if i == tree.tree_.feature[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "x > y > z" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "phi_x = 20 - phi_null" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "phi_y = 20 - phi_x - phi_null" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "phi_z = 20 - phi_y - phi_x - phi_null" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.0" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phi_z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "y > z > x" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "phi_y = (4 / 10) * 50 + (6 / 10) * (1 / 6 * 20 + 5 / 6 * 10) - phi_null" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4.0" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phi_y" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "phi_z = 0" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "phi_x = 20 - phi_y - phi_null" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-7.0" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "phi_x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([20.])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tree.predict([[150, 75, 200]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "X_test = pd.DataFrame({'x': [150], 'y': [75], 'z': [200]})" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Setting feature_perturbation = \"tree_path_dependent\" because no background data was given.\n" ] }, { "data": { "text/plain": [ "array([[-5., 2., 0.]])" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "explainer = shap.TreeExplainer(tree)\n", "shap_values = explainer.shap_values(X_test)\n", "shap_values" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.2" } }, "nbformat": 4, "nbformat_minor": 4 }