diff --git a/dianna/__init__.py b/dianna/__init__.py index 0dbb22d9..19ca0103 100644 --- a/dianna/__init__.py +++ b/dianna/__init__.py @@ -48,11 +48,11 @@ def explain_timeseries(model_or_function, timeseries_data, method, labels, **kwa """ explainer = _get_explainer(method, kwargs, modality="Timeseries") - explain_image_kwargs = utils.get_kwargs_applicable_to_function(explainer.explain, kwargs) + explain_timeseries_kwargs = utils.get_kwargs_applicable_to_function(explainer.explain, kwargs) return explainer.explain(model_or_function, timeseries_data, labels, - **explain_image_kwargs) + **explain_timeseries_kwargs) def explain_image(model_or_function, input_data, method, labels, **kwargs): diff --git a/tutorials/rise_timeseries_weather.ipynb b/tutorials/rise_timeseries_weather.ipynb index be21dc1d..31819073 100644 --- a/tutorials/rise_timeseries_weather.ipynb +++ b/tutorials/rise_timeseries_weather.ipynb @@ -2,67 +2,301 @@ "cells": [ { "cell_type": "markdown", + "source": [ + "\"Logo_ER10\"\n", + "\n", + "### Model Interpretation using RISE for timeseries data\n", + "This notebook shows how to apply the RISE explainability method on a model trained to classify timeseries data. Two examples are included here:\n", + "- Verify RISE for timeseries with a simple \"expert\" model\n", + "- Demonstrate RISE with a pretrained weather forecast (onnx) model\n", + "\n", + "It visualizes the relevance attributions for each segmentation of timeseries by displaying them on top of the timeseries.
\n", + "\n", + "RISE is short for Randomized Input Sampling for Explanation of Black-box Models. It estimates the relevance empirically by probing the model with randomly masked versions of the input image to obtain the corresponding outputs.
\n", + "\n", + "More details about this method can be found in the paper https://arxiv.org/abs/1806.07421.
" + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, + } + }, + { + "cell_type": "code", + "execution_count": 1, + "outputs": [], "source": [ - "## Exploration of RISE for timeseries with weather dataset" - ] + "import os\n", + "import pandas as pd\n", + "import numpy as np\n", + "from dianna import visualization\n", + "from matplotlib import pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "import onnx\n", + "import onnxruntime as ort\n", + "import dianna\n", + "\n", + "np.random.seed(0)" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", + "source": [ + "#### 1 - Create a mini dataset with extremes for verification\n", + "To demonstrate the skill of RISE for timeseries model explanation, we \"make up\" a weather dataset (timeseries) with extrem hot days and cold days." + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, + } + }, + { + "cell_type": "code", + "execution_count": 2, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAHHCAYAAACle7JuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA16UlEQVR4nO3de3RU5b3/8c/kNgmZMBBCbpJwi4Bya4saEREKMQEqSsV6V1B+iBiwmBZsrBpvPanYKvaI2NNzBO2RalFExQJHEUKrARREpOdwiygoBISahARJQmb//ogzcchtMiTZe5P3a61ZK7NnZ+brZhZ8fJ7nux+HYRiGAAAAbCjE7AIAAACCRZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABOhCHwxHQY/369WaXappnn31WS5YsMbsMAAFysNcS0HH893//t9/zF198Ue+8847+/Oc/+x2//PLLlZCQ0J6lWcagQYMUFxfXocMcYCdhZhcAoP3cfPPNfs83btyod955p97xs4VhGDp58qSioqKoAzhLMbUEwI/H49GCBQs0cOBARUZGKiEhQTNmzNA333zjd16vXr10xRVXaP369brgggsUFRWlwYMH+0Yyli9frsGDBysyMlLDhg3Txx9/7Pf7U6dOlcvl0meffaasrCxFR0crOTlZjzzyiE4fKG5pTWvWrPHV9Mc//lGStHjxYo0ZM0bx8fFyOp06//zztWjRonq//89//lMFBQW+abbRo0dLkh566CE5HI5612vJkiVyOBz6/PPPA6qjpKREc+bMUUpKipxOp9LS0vT444/L4/EE9gcEwA8jMgD8zJgxQ0uWLNFtt92mu+++W/v27dMzzzyjjz/+WO+//77Cw8N95+7du1c33nijZsyYoZtvvlm/+93vNHHiRD333HO67777dNddd0mS8vPzde2112rXrl0KCan7/6eamhqNGzdOF198sebPn6/Vq1crLy9Pp06d0iOPPBJUTbt27dINN9ygGTNmaPr06erfv78kadGiRRo4cKCuvPJKhYWF6a233tJdd90lj8ej7OxsSdKCBQs0e/ZsuVwu/frXv5akoKfYGqrjxIkTGjVqlL766ivNmDFDqamp+uCDD5Sbm6tDhw5pwYIFQX0W0KEZADqs7Oxs4/t/Dfz9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aKjZ5VmWx+PRnDlzNGLECA0aNEhS7fczIiJCXbp08TuX72fTGrqWknTjjTeqZ8+eSk5O1vbt23Xvvfdq165dWr58uYnVth+CDEw1fvx4389DhgxRenq6evbsqb/+9a+aNm2aiZUB/q6//nrfz4MHD9aQIUPUt29frV+/XmPHjjWxMmvLzs7Wjh07WPvWChq7lnfccYfv58GDByspKUljx45VUVGR+vbt295ltjumllooLi5OoaGh9VbXHz58WImJiSZVdfbo0qWL+vXrp71795pdiq15v4t8T9tOnz59FBcXx3e1CbNmzdLKlSu1bt069ejRw3c8MTFRVVVVKikp8Tuf72fjGruWDUlPT5ekDvPdJMi0UEREhIYNG6a1a9f6jnk8Hq1du1bDhw83sbKzQ3l5uYqKipSUlGR2KbbWu3dvJSYm+n1Py8rKtGnTJr6nreTLL7/UsWPH+K42wDAMzZo1S6+//rree+899e7d2+/1YcOGKTw83O/7uWvXLu3fv5/v52mau5YN2bZtmyR1mO8mU0tByMnJ0ZQpU3TBBRfooosu0oIFC1RRUaHbbrvN7NJs55e//KUmTpyonj176uDBg8rLy1NoaKhuuOEGs0uzvPLycr//49q3b5+2bdum2NhYpaamas6cOXrsscd07rnnqnfv3nrggQeUnJysSZMmmVe0hTV1PWNjY/Xwww9r8uTJSkxMVFFRkebNm6e0tDRlZWWZWLU1ZWdna+nSpXrjjTcUExPjW/fidrsVFRUlt9utadOmKScnR7GxsercubNmz56t4cOH6+KLLza5emtp7loWFRVp6dKlmjBhgrp166bt27frnnvu0WWXXaYhQ4aYXH07Mbttyq7+/d//3UhNTTUiIiKMiy66yNi4caPZJdnSddddZyQlJRkRERHGOeecY1x33XXG3r17zS7LFtatW2dIqveYMmWKYRi1LdgPPPCAkZCQYDidTmPs2LHGrl27zC3awpq6nidOnDAyMzON7t27G+Hh4UbPnj2N6dOnG8XFxWaXbUkNXUdJxuLFi33nfPvtt8Zdd91ldO3a1ejUqZPx05/+1Dh06JB5RVtUc9dy//79xmWXXWbExsYaTqfTSEtLM+bOnWuUlpaaW3g7chiGYbRncAIAAGgtrJEBAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZABAAC2RZAB0GqmTp1qyp2DlyxZUm8n5WCMHj1ac+bMOeP3AdB+2KIAQEAcDkeTr+fl5enpp5+WGffYvO666zRhwoR2/1wA5iPIAAjIoUOHfD+/8sorevDBB7Vr1y7fMZfLJZfLZUZpioqKUlRUlCmfDcBcTC0BCEhiYqLv4Xa75XA4/I65XK56U0ujR4/W7NmzNWfOHHXt2lUJCQn605/+5NtkNSYmRmlpaVq1apXfZ+3YsUPjx4+Xy+VSQkKCbrnlFh09erTR2k6fWnrooYf0gx/8QH/+85/Vq1cvud1uXX/99Tp+/LjvnIqKCt16661yuVxKSkrS73//+3rvW1lZqV/+8pc655xzFB0drfT0dK1fv16SdPLkSQ0cOFB33HGH7/yioiLFxMTo+eefb+HVBRAsggyANvXCCy8oLi5Omzdv1uzZszVz5kz97Gc/0yWXXKKtW7cqMzNTt9xyi06cOCFJKikp0ZgxY/TDH/5QH330kVavXq3Dhw/r2muvbdHnFhUVacWKFVq5cqVWrlypgoIC/fa3v/W9PnfuXBUUFOiNN97Q//zP/2j9+vXaunWr33vMmjVLhYWFevnll7V9+3b97Gc/07hx47Rnzx5FRkbqpZde0gsvvKA33nhDNTU1uvnmm3X55Zfr9ttvP/MLByAwJm9aCcCGFi9ebLjd7nrHp0yZYlx11VW+56NGjTIuvfRS3/NTp04Z0dHRxi233OI7dujQIUOSUVhYaBiGYTz66KNGZmam3/seOHDAkNTo7t2n15OXl2d06tTJKCsr8x2bO3eukZ6ebhiGYRw/ftyIiIgw/vrXv/peP3bsmBEVFWX8/Oc/NwzDML744gsjNDTU+Oqrr/w+a+zYsUZubq7v+fz58424uDhj1qxZRlJSknH06NEGawTQNlgjA6BNDRkyxPdzaGiounXrpsGDB/uOJSQkSJKOHDkiSfrkk0+0bt26BtfbFBUVqV+/fgF9bq9evRQTE+N7npSU5PuMoqIiVVVVKT093fd6bGys+vfv73v+6aefqqampt7nVVZWqlu3br7nv/jFL7RixQo988wzWrVqld9rANoeQQZAmwoPD/d77nA4/I55u6E8Ho8kqby8XBMnTtTjjz9e772SkpLO6HO9nxGI8vJyhYaGasuWLQoNDfV77fsh68iRI9q9e7dCQ0O1Z88ejRs3LuDPAHDmCDIALOVHP/qRXnvtNfXq1UthYW3zV1Tfvn0VHh6uTZs2KTU1VZL0zTffaPfu3Ro1apQk6Yc//KFqamp05MgRjRw5stH3uv322zV48GBNmzZN06dPV0ZGhs4777w2qRtAfSz2BWAp2dnZ+te//qUbbrhBH374oYqKirRmzRrddtttqqmpaZXPcLlcmjZtmubOnav33ntPO3bs0NSpUxUSUvdXYr9+/XTTTTfp1ltv1fLly7Vv3z5t3rxZ+fn5evvttyVJCxcuVGFhoV544QXddNNNmjRpkm666SZVVVW1Sp0AmkeQAWApycnJev/991VTU6PMzEwNHjxYc+bMUZcuXfyCxpl64oknNHLkSE2cOFEZGRm69NJLNWzYML9zFi9erFtvvVW/+MUv1L9/f02aNEkffvihUlNTtXPnTs2dO1fPPvusUlJSJEnPPvusjh49qgceeKDV6gTQNIdhmHAbTgAAgFbAiAwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALAtggwAALCt/w/bIyQsKFZ6VwAAAABJRU5ErkJggg==\n" + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "This notebook shows how to use the RISE for timeseries explainer to explain trained onnx model with weather dataset." - ] + "# make up a weather dataset with extrems\n", + "cold_with_2_hot_days = np.expand_dims(np.array([30, 29] + list(np.zeros(26))) , axis=1)\n", + "data_extreme = cold_with_2_hot_days\n", + "fig = plt.figure()\n", + "plt.plot(data_extreme)\n", + "plt.xlabel(\"Time index\")\n", + "plt.ylabel(\"Celcius\")\n", + "plt.title(\"Temperature\")\n", + "plt.show()" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "markdown", + "source": [ + "#### 2 - Define an \"expert\" model to verify RISE for timeseries\n", + "We can define an 'expert' model to test RISE. This expert model decides it's summer if the mean temp is above the threshold, and winter in other cases." + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%% md\n" } - }, - "source": [ - "### Load weather dataset" - ] + } }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, + "outputs": [], + "source": [ + "# We define a threshold for the model to make decisions\n", + "# The label is [\"summer\", \"winter\"]\n", + "threshold = 14\n", + "\n", + "def run_expert_model(data):\n", + " is_summer = np.mean(np.mean(data, axis=1), axis=1) > threshold\n", + " number_of_classes = 2\n", + " number_of_instances = data.shape[0]\n", + " result = np.zeros((number_of_instances ,number_of_classes))\n", + " result[is_summer] = [1.0, 0.0]\n", + " result[~is_summer] = [0.0, 1.0]\n", + " return result" + ], "metadata": { + "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "markdown", + "source": [ + "#### 3 - Compute and visualize the relevance scores\n", + "In this section we compute the relevance scores for each segment of timeseries using RISE and visualize them on the original timeseries." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "RISE masks random portions of the input timseries based on given segmentations and passes the masked timeseries through the model — the masked portion that decreases accuracy the most is the most “important” portion.
\n", + "\n", + "To call the explainer and generate relevance scores map, the user need to specifiy the number of masks being randomly generated (`n_masks`), the resolution of features in masks (`feature_res`) and for each mask and each feature in the image, the probability of being kept unmasked (`p_keep`).
\n", + "\n", + "Also, we need to define the approach for masking (`mask_type`). Since our data is highly skewed, here we make the masked data to be the \"threshold\" value instead of the mean." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": 4, "outputs": [], "source": [ - "import os\n", - "import pandas as pd\n", - "import numpy as np\n", - "from sklearn.model_selection import train_test_split\n", - "import onnx\n", - "import onnxruntime as ort\n", - "import dianna\n", - "np.random.seed(0)" - ] + "# we use the threshold to mask the data\n", + "def input_train_mean(_data):\n", + " return threshold" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Explaining: 100%|██████████| 100/100 [00:00<00:00, 24949.76it/s]\n" + ] + } + ], + "source": [ + "# call the explainer\n", + "explanation = dianna.explain_timeseries(run_expert_model, timeseries_data=data_extreme,\n", + " method='rise', labels=[0,1], p_keep=0.1,\n", + " n_masks=10000, mask_type=input_train_mean)" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Now we can visualize the relevance scores on top of the displayed timeseries using the visualization tool in dianna." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": 6, + "outputs": [ + { + "data": { + "text/plain": "
", + "image/png": "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\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": "" + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Normalize the explanation scores for the purpose of visualization\n", + "def normalize(data):\n", + " \"\"\"Squash all values into [-1,1] range.\"\"\"\n", + " zero_to_one = (data - np.min(data)) / (np.max(data) - np.min(data))\n", + " return 2*zero_to_one -1\n", + "\n", + "heatmap_channel = normalize(explanation[0])\n", + "segments = []\n", + "for i in range(len(heatmap_channel) - 1):\n", + " segments.append({\n", + " 'index': i,\n", + " 'start': i - 0.5,\n", + " 'stop': i + 0.5,\n", + " 'weight': heatmap_channel[i]})\n", + "visualization.plot_timeseries(range(len(heatmap_channel)), data_extreme,\n", + " segments, xlabel=\"Time index\", ylabel=\"Temperature\",\n", + " show_plot=True)" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "Here we plot the explanation for the classification of summer. The results are consistent with our expectation as it marks all hot days in the timeseries.
\n", + "\n", + "Now let's try out RISE with a weather prediction dataset from real life.
\n", + "Here is the doi to this dataset:
\n", + "10.5281/zenodo.4770936" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "markdown", + "source": [ + "#### 4 - Loading the weather prediction dataset\n", + "Downloading the weather prediction dataset from zenodo." + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, + { + "cell_type": "code", + "execution_count": 7, "outputs": [ { "data": { "text/plain": " DATE MONTH BASEL_cloud_cover BASEL_humidity \\\ncount 3.654000e+03 3654.000000 3654.000000 3654.000000 \nmean 2.004568e+07 6.520799 5.418446 0.745107 \nstd 2.874287e+04 3.450083 2.325497 0.107788 \nmin 2.000010e+07 1.000000 0.000000 0.380000 \n25% 2.002070e+07 4.000000 4.000000 0.670000 \n50% 2.004567e+07 7.000000 6.000000 0.760000 \n75% 2.007070e+07 10.000000 7.000000 0.830000 \nmax 2.010010e+07 12.000000 8.000000 0.980000 \n\n BASEL_pressure BASEL_global_radiation BASEL_precipitation \\\ncount 3654.000000 3654.000000 3654.000000 \nmean 1.017876 1.330380 0.234849 \nstd 0.007962 0.935348 0.536267 \nmin 0.985600 0.050000 0.000000 \n25% 1.013300 0.530000 0.000000 \n50% 1.017700 1.110000 0.000000 \n75% 1.022700 2.060000 0.210000 \nmax 1.040800 3.550000 7.570000 \n\n BASEL_sunshine BASEL_temp_mean BASEL_temp_min ... \\\ncount 3654.000000 3654.000000 3654.000000 ... \nmean 4.661193 11.022797 6.989135 ... \nstd 4.330112 7.414754 6.653356 ... \nmin 0.000000 -9.300000 -16.000000 ... \n25% 0.500000 5.300000 2.000000 ... \n50% 3.600000 11.400000 7.300000 ... \n75% 8.000000 16.900000 12.400000 ... \nmax 15.300000 29.000000 20.800000 ... \n\n STOCKHOLM_temp_min STOCKHOLM_temp_max TOURS_wind_speed \\\ncount 3654.000000 3654.000000 3654.000000 \nmean 5.104215 11.470635 3.677258 \nstd 7.250744 8.950217 1.519866 \nmin -19.700000 -14.500000 0.700000 \n25% 0.000000 4.100000 2.600000 \n50% 5.000000 11.000000 3.400000 \n75% 11.200000 19.000000 4.600000 \nmax 21.200000 32.900000 10.800000 \n\n TOURS_humidity TOURS_pressure TOURS_global_radiation \\\ncount 3654.000000 3654.000000 3654.000000 \nmean 0.781872 1.016639 1.369787 \nstd 0.115572 0.018885 0.926472 \nmin 0.330000 0.000300 0.050000 \n25% 0.700000 1.012100 0.550000 \n50% 0.800000 1.017300 1.235000 \n75% 0.870000 1.022200 2.090000 \nmax 1.000000 1.041400 3.560000 \n\n TOURS_precipitation TOURS_temp_mean TOURS_temp_min TOURS_temp_max \ncount 3654.000000 3654.000000 3654.000000 3654.000000 \nmean 0.186100 12.205802 7.860536 16.551779 \nstd 0.422151 6.467155 5.692256 7.714924 \nmin 0.000000 -6.200000 -13.000000 -3.100000 \n25% 0.000000 7.600000 3.700000 10.800000 \n50% 0.000000 12.300000 8.300000 16.600000 \n75% 0.160000 17.200000 12.300000 22.400000 \nmax 6.200000 31.200000 22.600000 39.800000 \n\n[8 rows x 165 columns]", "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
DATEMONTHBASEL_cloud_coverBASEL_humidityBASEL_pressureBASEL_global_radiationBASEL_precipitationBASEL_sunshineBASEL_temp_meanBASEL_temp_min...STOCKHOLM_temp_minSTOCKHOLM_temp_maxTOURS_wind_speedTOURS_humidityTOURS_pressureTOURS_global_radiationTOURS_precipitationTOURS_temp_meanTOURS_temp_minTOURS_temp_max
count3.654000e+033654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.000000...3654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.0000003654.000000
mean2.004568e+076.5207995.4184460.7451071.0178761.3303800.2348494.66119311.0227976.989135...5.10421511.4706353.6772580.7818721.0166391.3697870.18610012.2058027.86053616.551779
std2.874287e+043.4500832.3254970.1077880.0079620.9353480.5362674.3301127.4147546.653356...7.2507448.9502171.5198660.1155720.0188850.9264720.4221516.4671555.6922567.714924
min2.000010e+071.0000000.0000000.3800000.9856000.0500000.0000000.000000-9.300000-16.000000...-19.700000-14.5000000.7000000.3300000.0003000.0500000.000000-6.200000-13.000000-3.100000
25%2.002070e+074.0000004.0000000.6700001.0133000.5300000.0000000.5000005.3000002.000000...0.0000004.1000002.6000000.7000001.0121000.5500000.0000007.6000003.70000010.800000
50%2.004567e+077.0000006.0000000.7600001.0177001.1100000.0000003.60000011.4000007.300000...5.00000011.0000003.4000000.8000001.0173001.2350000.00000012.3000008.30000016.600000
75%2.007070e+0710.0000007.0000000.8300001.0227002.0600000.2100008.00000016.90000012.400000...11.20000019.0000004.6000000.8700001.0222002.0900000.16000017.20000012.30000022.400000
max2.010010e+0712.0000008.0000000.9800001.0408003.5500007.57000015.30000029.00000020.800000...21.20000032.90000010.8000001.0000001.0414003.5600006.20000031.20000022.60000039.800000
\n

8 rows × 165 columns

\n
" }, - "execution_count": 2, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -85,8 +319,8 @@ { "cell_type": "markdown", "source": [ - "### Prepare dataset\n", - "Given how the classification model is trained, we prepare the testing data for prediction." + "Given how the classification model is trained, we prepare the testing data for prediction.
\n", + "To make it simpler, we only choose one location and make it a binary classification task, to determine whether it is summer or winter." ], "metadata": { "collapsed": false, @@ -97,21 +331,21 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 8, "outputs": [ { "data": { "text/plain": " DE_BILT_temp_max\ncount 3654.000000\nmean 14.798604\nstd 7.210740\nmin -4.700000\n25% 9.200000\n50% 14.900000\n75% 20.200000\nmax 35.700000", "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
DE_BILT_temp_max
count3654.000000
mean14.798604
std7.210740
min-4.700000
25%9.200000
50%14.900000
75%20.200000
max35.700000
\n
" }, - "execution_count": 3, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# select only data from De Bilt\n", - "columns = [col for col in data.columns if col.startswith('DE_BILT') and col.endswith('temp_max')]#[:9]\n", + "# select only data from one location (De Bilt)\n", + "columns = [col for col in data.columns if col.startswith('DE_BILT') and col.endswith('temp_max')]\n", "data_debilt = data[columns]\n", "data_debilt.describe()" ], @@ -124,7 +358,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 9, "outputs": [ { "name": "stdout", @@ -160,16 +394,28 @@ } } }, + { + "cell_type": "markdown", + "source": [ + "We label the data based on the seasons.
\n", + "To simplify the problem, we make it a binary classification task and only select summer and winter.
" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%% md\n" + } + } + }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 10, "outputs": [ { "data": { - "text/plain": " 0 1 2 3\ncount 120.000000 120.000000 120.000000 120.000000\nmean 0.250000 0.250000 0.250000 0.250000\nstd 0.434828 0.434828 0.434828 0.434828\nmin 0.000000 0.000000 0.000000 0.000000\n25% 0.000000 0.000000 0.000000 0.000000\n50% 0.000000 0.000000 0.000000 0.000000\n75% 0.250000 0.250000 0.250000 0.250000\nmax 1.000000 1.000000 1.000000 1.000000", - "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
0123
count120.000000120.000000120.000000120.000000
mean0.2500000.2500000.2500000.250000
std0.4348280.4348280.4348280.434828
min0.0000000.0000000.0000000.000000
25%0.0000000.0000000.0000000.000000
50%0.0000000.0000000.0000000.000000
75%0.2500000.2500000.2500000.250000
max1.0000001.0000001.0000001.000000
\n
" + "text/plain": "(60, 28, 1)" }, - "execution_count": 5, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -180,41 +426,19 @@ "\n", "# one class per meteorological season\n", "labels = np.zeros_like(months, dtype=int)\n", - "spring = (3 <= months) & (months <= 5) # mar - may\n", "summer = (6 <= months) & (months <= 8) # jun - aug\n", - "autumn = (9 <= months) & (months <= 11) # sep - nov\n", "winter = (months <= 2) | (months == 12) # dec - feb\n", "\n", - "labels[spring] = 0\n", - "labels[summer] = 1\n", - "labels[autumn] = 2\n", - "labels[winter] = 3\n", + "labels[summer] = 0\n", + "labels[winter] = 1\n", "\n", - "target = pd.get_dummies(labels)\n", + "target = pd.get_dummies(labels[summer + winter])\n", "\n", - "classes = ['spring', 'summer', 'autumn', 'winter']\n", + "classes = ['summer', 'winter']\n", "nclass = len(classes)\n", "\n", - "target.describe()" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 6, - "outputs": [], - "source": [ - "classes = ['summer', 'winter']\n", - "nclass = 2\n", - "labels[summer] = 0\n", - "labels[winter] = 1\n", - "target = pd.get_dummies(labels[summer + winter])\n", - "data_ts = data_ts[summer + winter]" + "data_ts = data_ts[summer + winter]\n", + "data_ts.shape" ], "metadata": { "collapsed": false, @@ -226,7 +450,7 @@ { "cell_type": "markdown", "source": [ - "### Train/test split" + "Train/test split" ], "metadata": { "collapsed": false, @@ -237,7 +461,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 11, "outputs": [ { "name": "stdout", @@ -262,7 +486,7 @@ { "cell_type": "markdown", "source": [ - "### Check predictions with ONNX model" + "Load ONNX model and create a ONNX model runner." ], "metadata": { "collapsed": false, @@ -273,7 +497,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 12, "outputs": [], "source": [ "# onnx model available on surf drive\n", @@ -294,7 +518,6 @@ "\n", " onnx_input = {input_name: data.astype(np.float32)}\n", " pred_onnx = sess.run([output_name], onnx_input)[0]\n", - " print(f'mean:{np.mean(data)}, prediction:{pred_onnx}')\n", " \n", " return pred_onnx" ], @@ -306,43 +529,27 @@ } }, { - "cell_type": "code", - "execution_count": 9, - "outputs": [], + "cell_type": "markdown", "source": [ - "# We can use this 'expert' model instead of a trained model. This expert model decides it's summer if the mean temp is\n", - "# above some threshold, and winter in other cases.\n", - "\n", - "def run_expert_model(data):\n", - " is_summer = np.mean(np.mean(data, axis=1), axis=1) > 14\n", - " print(f'{is_summer=}')\n", - " number_of_classes = 2\n", - " number_of_instances = data.shape[0]\n", - " result = np.zeros((number_of_instances ,number_of_classes))\n", - " result[is_summer] = [1.0, 0.0]\n", - " result[~is_summer] = [0.0, 1.0]\n", - " return result" + "Select an instance to explain and check the prediction with the model." ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%% md\n" } } }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 13, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "is_summer=array([False])\n", "The predicted class is: winter\n", - "The actual class is: winter\n", - "(1, 28) [[8.1 8.7 9.6 9.4 7.4 9.1 7.4 8.1 7. 4.3 4.4 2.6 3.6 4. 5.4 6.9 7.5 8.6\n", - " 5.6 6.1 7.8 6.1 4.4 0.9 2.8 5.5 3.8 5.9]]\n" + "The actual class is: winter\n" ] } ], @@ -350,12 +557,10 @@ "idx = 6 # explained instance\n", "data_instance = data_test[idx][np.newaxis, ...]\n", "# precheck ONNX predictions\n", - "pred_onnx = run_expert_model(data_instance)\n", + "pred_onnx = run_model(data_instance)\n", "pred_class = classes[np.argmax(pred_onnx)]\n", "print(\"The predicted class is:\", pred_class)\n", - "print(\"The actual class is:\", classes[np.argmax(target_test.iloc[idx])])\n", - "input_image = data_instance[0]\n", - "print(input_image.T.shape, input_image.T)" + "print(\"The actual class is:\", classes[np.argmax(target_test.iloc[idx])])" ], "metadata": { "collapsed": false, @@ -365,1417 +570,196 @@ } }, { - "cell_type": "code", - "execution_count": 11, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(1, 28) [[30.]\n", - " [29.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]\n", - " [ 0.]]\n" - ] - } - ], + "cell_type": "markdown", "source": [ - "very_cold_to_super_hot = np.expand_dims(np.arange(-6, 35, 1.5), axis=1)\n", - "very_cold = np.expand_dims(np.arange(-6, -4, 1/14), axis=1)\n", - "very_hot = np.expand_dims(np.arange(30, 28, -1/14), axis=1)\n", - "cold_with_2_hot_days = np.expand_dims(np.array([30, 29] + list(np.zeros(26))) , axis=1)\n", - "input_image = cold_with_2_hot_days\n", - "print(input_image.T.shape, input_image)" + "#### 5 - Compute and visualize the relevance scores\n", + "In this section we compute the relevance scores for each segment of timeseries using RISE and visualize them on the original timeseries." ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%% md\n" } } }, { "cell_type": "code", - "execution_count": 12, - "outputs": [ - { - "data": { - "text/plain": "['DE_BILT_temp_max']" - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "outputs": [], "source": [ - "columns" + "# call the explainer\n", + "explanation = dianna.explain_timeseries(run_model, timeseries_data=data_instance[0],\n", + " method='rise', labels=[0,1], p_keep=0.1,\n", + " n_masks=10000)" ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%%\n", + "is_executing": true } } }, { - "cell_type": "code", - "execution_count": 13, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "using mean 14.649444444444446\n" - ] - } - ], + "cell_type": "markdown", "source": [ - "train_mean = np.mean(data_train)\n", - "print('using mean ', train_mean)\n", - "def input_train_mean(_data):\n", - " return train_mean" + "Now we can visualize the relevance scores on top of the displayed timeseries using the visualization tool in dianna." ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%% md\n" } } }, { "cell_type": "code", - "execution_count": 14, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Explaining: 100%|██████████| 100/100 [00:00<00:00, 4349.95it/s]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "is_summer=array([False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, True, True, False, True, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " True, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, True, False, True, False, False, False, True, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, True, False, False, False, False,\n", - " True, False, False, False, True, True, False, False, True,\n", - " False, False, False, False, True, False, False, True, True,\n", - " False, False, True, True, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, True, False, False, True, False, False, True,\n", - " True, False, False, True, True, True, False, True, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, True, False, False, True, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, False, False, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " True, True, False, False, True, False, False, True, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, True, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, True, False, False, False, False,\n", - " False, True, True, False, False, False, False, True, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, True, True, True, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, True, False, False, False, True, False, True,\n", - " False, True, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, True, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, True, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, True, False, False, True, True, False, False,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, True, True, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, True, True, False, False, False, False, False, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " True, True, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, True, False, False, True, False, True, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, True, False, False, True, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, True, False, True, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, True, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, True, True, True, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, True, False, True, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, True, False, True, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, True, True, False,\n", - " False, True, False, False, False, True, False, False, False,\n", - " False, False, False, True, False, False, True, True, False,\n", - " False, False, False, True, False, True, False, True, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, True, True, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, True, True, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False, False, True, False, False, False, False, True, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, True, True, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, True, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, True, True, True, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, False, False, True, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " True, False, False, True, False, False, False, False, True,\n", - " False, False, False, False, False, False, True, False, True,\n", - " True, False, False, False, True, False, True, False, False,\n", - " False])\n", - "is_summer=array([False, True, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, True, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, True, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, True, False, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, True, False, True, False, True, False, False, False,\n", - " True, True, False, False, True, False, False, False, False,\n", - " False, True, False, False, True, False, False, False, False,\n", - " True, True, True, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, True, False, False, True, False, False, True, True,\n", - " True, False, False, False, True, True, True, False, False,\n", - " False, True, False, False, True, False, False, True, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, True, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, True, False, True, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, True, True, False, True, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, True, False, False, True, False, False, True,\n", - " True])\n", - "is_summer=array([False, False, True, True, False, False, True, True, False,\n", - " True, False, False, True, False, False, True, False, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, True, False, False, False, False, False, True,\n", - " False, True, True, True, False, False, False, True, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, True, True, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, True, False, True, False, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, True, False, True, False, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " True, True, True, False, False, False, False, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " True, False, True, False, False, True, False, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " True, False, True, False, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " False, True, False, False, False, True, False, False, False,\n", - " True, False, False, True, False, True, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, True, True, True, True, False, False, False, True,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, True, False, True, False,\n", - " True, False, True, True, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, True, False, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, True, False, False, False, False, True,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, True, False, False, True, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, True, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, True, False, True, False, False, True, False, False,\n", - " False, False, True, False, True, False, False, True, False,\n", - " False, False, True, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, True, False, False, True, False, False, True, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, False, False, False, False, True, True,\n", - " False, True, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, True, False, True, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, True, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, True, True, True, False, False, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, True, False, False, True, True, False, True,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, False, True, False, True, False, False, False, False,\n", - " True, False, True, False, False, True, True, False, True,\n", - " False, False, False, False, False, True, False, False, False,\n", - " True, False, True, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, True, False, True,\n", - " False])\n", - "is_summer=array([False, True, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, True, False, True, True, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " True, True, False, True, False, True, False, False, False,\n", - " False, False, False, False, True, False, True, True, False,\n", - " False, False, False, True, False, False, False, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, True, True, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, True, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, True, False, True,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " True, True, False, False, False, False, False, False, True,\n", - " False, False, True, False, True, False, True, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, True, True, False, True, True, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, True, True, False, True, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, True, True, False, False, False, True, False,\n", - " False, False, False, True, False, True, False, False, False,\n", - " False, False, False, False, False, False, True, True, True,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, True, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, True, False, True,\n", - " False, False, False, True, False, False, False, False, True,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, True, False, False, True, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False, False, False, False, True, False, False, True, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, True, False, True, False, False, True, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " True, True, True, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, True, False, False, False, True, False,\n", - " False, False, True, False, True, True, False, False, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " False, False, True, False, False, True, False, False, True,\n", - " False, False, False, False, False, True, False, False, True,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, True, False, False, True, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, True, True, True,\n", - " False, False, True, False, True, True, True, True, False,\n", - " False, False, False, False, True, True, False, False, True,\n", - " False, False, False, False, True, True, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, True, False, False, False, False, False, False,\n", - " False, True, True, True, False, False, False, False, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False])\n", - "is_summer=array([False, False, True, True, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, True, False, False, True, True, True,\n", - " False, False, False, True, False, False, False, False, True,\n", - " True, True, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, True, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, True, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, True, True, False, True, False, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False, True, True, False, False, True, False, False, True,\n", - " False, False, False, False, True, False, True, False, False,\n", - " True, False, False, False, True, False, True, True, False,\n", - " True, True, False, True, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, True, False, True, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, True, False, False, True, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, True, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, True, False, True, False, False, False, True, True,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([ True, False, False, True, False, False, False, False, False,\n", - " False, False, False, True, False, False, True, False, False,\n", - " False, False, True, True, False, False, False, True, False,\n", - " True, False, True, False, False, True, False, True, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False, True, True, True, True, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False])\n", - "is_summer=array([ True, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, True, False, True, False, True, False,\n", - " False, True, True, False, False, False, False, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, True, True, False, True, True, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " False, False, False, True, False, True, True, True, False,\n", - " False])\n", - "is_summer=array([False, True, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " False, True, False, False, False, True, False, False, False,\n", - " False, False, False, True, False, True, False, False, False,\n", - " False, False, True, False, False, False, True, False, False,\n", - " False, True, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, False, True, False, True,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, True, False, True, True,\n", - " False, True, False, False, False, True, False, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, True, False, False, True,\n", - " False, False, False, True, False, False, True, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, True, False, True, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, False, False, True, False, True, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, True, False, False, True, False,\n", - " False, True, False, False, False, False, False, True, True,\n", - " False, False, False, False, True, False, False, True, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " True, True, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, True, False, False, False, False, True, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, True, True, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, True, True, False, True,\n", - " False, False, True, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, True, True, False, True,\n", - " False, False, False, True, True, False, True, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, True, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " True, False, False, False, False, True, False, False, False,\n", - " False, True, False, False, False, False, True, True, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, True, False, False,\n", - " False, False, False, True, False, False, True, False, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, True, True, False, False, True,\n", - " False, False, True, False, False, True, False, False, False,\n", - " True, False, True, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, True, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " True])\n", - "is_summer=array([False, False, True, False, True, False, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, True, False, False, False, True, True, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, False, False, True, False, True, False,\n", - " False, True, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False, False, False, True, False, True, False, False, True,\n", - " False, True, True, False, False, False, False, True, False,\n", - " True, False, False, False, True, True, True, True, True,\n", - " False, False, False, False, False, False, False, True, True,\n", - " True, True, False, True, True, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, False, True, False, False, False, False,\n", - " True, True, True, True, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, True, False, True, False, False, False, False, True,\n", - " False, False, False, True, False, True, True, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, True, False, True, True, False, False, False, False,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, True, False, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, True,\n", - " False, False, False, True, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, True, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, True, False, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, True, True,\n", - " True, True, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, True, True, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, True, False, False, True, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, True, True, True, False, False, False, False, False,\n", - " True, False, False, False, True, False, True, True, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, True, True, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, True, False, False, False, True, True,\n", - " True, False, False, True, False, True, False, False, False,\n", - " True, True, False, True, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " True, True, False, False, False, False, False, False, True,\n", - " False, False, False, True, True, True, False, True, True,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, True, False, False, False, False,\n", - " False, True, False, True, False, True, False, False, False,\n", - " True, True, False, False, False, False, False, False, True,\n", - " False, False, False, False, True, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, False, False, True, False, False, False, False, True,\n", - " True, True, True, False, True, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, True, False, False, False, False, True, False, True,\n", - " False, False, False, False, True, False, True, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, False, True, True, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, True, False, True, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, True, False, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, True, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " True, False, True, False, True, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, True, False, False, True, False, False, False, True,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([ True, True, True, True, False, False, True, False, False,\n", - " False, False, False, True, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([False, True, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, True, True, False, True, False,\n", - " False, True, False, False, True, False, True, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, True, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, True, True, False, True, True, False, False, False,\n", - " False, False, False, False, False, True, True, False, False,\n", - " True, False, True, False, True, False, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, True, True, False, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, True, False, False, True, False, False, True,\n", - " False, False, False, True, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, True, False, True, True, True, True, False, False,\n", - " False, False, False, True, True, True, True, False, False,\n", - " False, False, False, False, True, True, False, True, False,\n", - " True, True, False, False, False, False, True, False, True,\n", - " True])\n", - "is_summer=array([False, False, False, False, True, False, False, False, False,\n", - " False, False, True, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, False, False, True, False, True, False, False,\n", - " True, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, True, True, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " True, False, True, False, False, False, False, True, False,\n", - " False, False, True, False, True, False, False, False, True,\n", - " False, True, False, True, False, False, False, False, False,\n", - " True, True, True, False, False, True, False, False, False,\n", - " True, True, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([ True, True, False, False, False, True, False, False, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, True, False, False, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, True, False, False, True, True, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, True, True, True, False, False, False,\n", - " True, False, False, True, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, True, True, False, False, False, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, True, True,\n", - " False, False, False, True, False, True, True, False, True,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, True, True, False, False, True, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " True, True, False, False, True, False, False, False, False,\n", - " True, False, False, False, False, True, False, False, False,\n", - " False, True, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, True, False, True, True, False, False,\n", - " False, True, False, False, True, False, True, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, True, True, True, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, True, False,\n", - " True, True, False, False, False, True, False, True, False,\n", - " False, True, True, False, False, False, False, False, False,\n", - " False, True, False, False, False, True, False, False, False,\n", - " False, True, False, True, False, False, True, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, True, True,\n", - " True])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, False, True, False, False, False, False,\n", - " False, False, False, True, False, True, False, True, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False])\n", - "is_summer=array([ True, True, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, True, True, False, False, False, False, True,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, True, False, True, False, True, True, True, True,\n", - " False, False, False, True, False, False, False, True, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([ True, True, False, False, False, False, True, False, False,\n", - " False, False, False, True, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, False, True, False, False, False,\n", - " False, False, False, True, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, True, False, True, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, True, False, False, True, False, False, True,\n", - " False, False, True, True, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, True, False, False, False,\n", - " False, False, True, False, False, False, True, False, False,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, True, False, False, True,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, True, False, True, False, False, False, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, True, False, False, True, True, False,\n", - " False, True, True, False, False, False, False, False, True,\n", - " False, True, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, True, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, True, False, True, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, True, False, True, False, False, False,\n", - " False, True, False, True, False, False, False, False, True,\n", - " False, False, False, True, True, True, False, True, False,\n", - " False])\n", - "is_summer=array([ True, True, False, True, False, False, False, False, False,\n", - " False, False, True, False, True, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, True, True, False, False, False, False,\n", - " False, False, False, True, True, False, False, True, True,\n", - " False, False, False, False, True, True, True, True, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, True, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, True, True, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, True, True, False, False, False, True, False, False,\n", - " True, True, False, False, True, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, True, False, True, False, True,\n", - " True, False, True, False, False, False, False, True, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, True, False, False, False,\n", - " False, True, False, False, False, True, False, False, True,\n", - " True, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, True, True, False,\n", - " False, False, False, True, True, False, False, False, True,\n", - " False, False, True, False, False, True, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, True, False, True,\n", - " False, True, True, True, True, False, True, False, False,\n", - " True, True, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, True, True, False, True, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, True, False, True, True, False, True,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, True, True, True, False,\n", - " False, False, True, False, True, True, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, True,\n", - " True, False, True, False, True, False, False, True, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, True,\n", - " False, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, True, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, True, False, False, False, True, False,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, True, False,\n", - " False, True, False, False, True, False, False, True, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, False, False, True, False, False, False, True, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, True, False, False, False, False, False,\n", - " False, True, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, True, True, True,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, True, True, False,\n", - " True, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, True, True, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, True,\n", - " False, False, False, False, True, False, True, False, False,\n", - " True, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, True, True, True, False,\n", - " False, False, False, True, False, False, False, True, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, False, False, False, True, False, True,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, False, True, True, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, True, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, True, False, False, False, True, False, False, True,\n", - " True, False, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, True, False, True,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, True, True, False, True, True, False, False,\n", - " False, True, False, False, False, False, False, True, False,\n", - " True, False, True, False, True, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, True, True, True, False, True, False, False,\n", - " False, True, False, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, True, False, False, True, False, True,\n", - " False, False, False, True, True, False, False, False, False,\n", - " True])\n", - "is_summer=array([ True, False, True, False, False, True, False, True, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, True, False, False, False, False, True,\n", - " True, False, False, True, True, False, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, True, True, False, False, True, True, True,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " True, False, True, True, False, False, False, False, True,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False])\n", - "is_summer=array([ True, False, True, False, False, False, False, True, True,\n", - " True, False, False, False, False, False, True, False, True,\n", - " False, True, True, False, False, False, False, True, False,\n", - " True, False, False, True, False, False, True, True, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True, False, True, True, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, True, True, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([ True, False, False, False, False, True, True, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, True, False, False, False,\n", - " False])\n", - "is_summer=array([ True, False, True, True, False, False, True, False, True,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, True, False, False, True, False, False, True,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, True, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, True, True,\n", - " True])\n", - "is_summer=array([False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, True, True, False, True,\n", - " False, False, False, False, False, True, True, False, False,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, False, False, True, False, True, True, True, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, False, True, False, True, True, True, False, False,\n", - " False, False, True, False, False, False, True, False, True,\n", - " False, False, False, False, False, False, False, False, True,\n", - " False, False, False, False, True, False, False, True, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " False])\n", - "is_summer=array([False, False, True, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, True,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, True, False, True, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, True, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, True, False, False, False, True, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, True, False, False, True, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, True, False, False, False,\n", - " False, False, False, True, False, False, True, False, True,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, True, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, True, False, False, False, False, True, False, False,\n", - " True, True, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, True, True, True, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " True, False, False, False, False, True, False, False, False,\n", - " True, False, False, True, False, False, False, True, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, True, False, False, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " False, True, True, True, False, False, False, False, True,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, True, False, True, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([False, False, False, False, False, False, True, True, False,\n", - " True, False, False, False, False, False, False, False, True,\n", - " False, False, True, False, True, False, True, False, True,\n", - " False, True, False, False, False, False, False, False, False,\n", - " True, True, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, True, True, False,\n", - " False, False, False, True, True, False, False, False, False,\n", - " False, True, False, True, False, False, False, False, True,\n", - " False, False, False, True, False, False, False, True, False,\n", - " True, True, False, False, False, False, True, False, False,\n", - " False])\n", - "is_summer=array([False, False, True, True, False, False, False, False, False,\n", - " True, True, True, False, True, False, False, False, True,\n", - " True, False, False, False, False, True, True, False, False,\n", - " False, False, True, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, True, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False, False, True, False, False, False, True, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, False,\n", - " False, False, True, False, True, False, True, False, False,\n", - " False, False, False, True, True, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, False, False, True, True, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True, False, True, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, False,\n", - " True, False, True, True, False, False, True, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, True, False, False, False, True,\n", - " False])\n", - "is_summer=array([False, True, True, True, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, True, True, False, False, False,\n", - " False, True, False, False, False, False, False, False, True,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " False, False, False, False, False, False, False, True, False,\n", - " False, False, True, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, False, False, False, False, False,\n", - " True])\n", - "is_summer=array([ True, False, True, False, True, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True, True, False, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, True, False, False, True,\n", - " True, False, False, False, False, False, False, False, False,\n", - " True, False, False, False, False, False, False, False, False,\n", - " False, False, True, False, True, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, True, True, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False])\n", - "is_summer=array([False, False, False, False, False, False, False, False, False,\n", - " True, True, False, False, False, False, False, False, False,\n", - " False, False, True, False, True, True, False, False, False,\n", - " False, False, True, False, False, False, True, False, False,\n", - " True, False, False, False, False, False, False, True, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, True, False, False, False, False, False,\n", - " False, False, True, False, True, False, False, False, False,\n", - " True, False, True, False, False, True, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " False, False, False, False, False, False, False, False, False,\n", - " True])\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "execution_count": null, + "outputs": [], "source": [ - "explanation = dianna.explain_timeseries(run_expert_model, timeseries_data=input_image, method='rise', labels=[0,1], p_keep=0.1, n_masks=10000, mask_type=input_train_mean)" + "heatmap_channel = normalize(explanation[np.argmax(pred_onnx)])\n", + "segments = []\n", + "for i in range(len(heatmap_channel) - 1):\n", + " segments.append({\n", + " 'index': i,\n", + " 'start': i - 0.5,\n", + " 'stop': i + 0.5,\n", + " 'weight': heatmap_channel[i]})\n", + "visualization.plot_timeseries(range(len(heatmap_channel)), data_instance[0],\n", + " segments, xlabel=\"Time index\", ylabel=\"Temperature\",\n", + " show_plot=True)" ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%%\n", + "is_executing": true } } }, { - "cell_type": "code", - "execution_count": 15, - "outputs": [ - { - "data": { - "text/plain": "array([[1.044, 1.048, 0.142, 0.181, 0.129, 0.145, 0.157, 0.173, 0.163,\n 0.146, 0.15 , 0.143, 0.141, 0.14 , 0.174, 0.146, 0.143, 0.153,\n 0.152, 0.144, 0.167, 0.165, 0.149, 0.157, 0.14 , 0.146, 0.142,\n 0.171]])" - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "cell_type": "markdown", "source": [ - "explanation[0].T" + "#### 6 - Conclusions\n", + "The relevance scores are generated by passing multiple randomly masked inputs to the black-box model and averaging their segment-wise relevances. The idea behind this is that whenever a mask preserves important parts of the timeseries it gets higher score.
\n", + "\n", + "The first example with a designed timeseries and an expert model demonstrates that RISE is able to identify the important segments for the classification in a simplified case.\n", + "\n", + "The second example shows that the method still runs in a more case with real data and a real model. It is, however, hard to understand the explanation of this case. This could be due to an imperfecty trained model, not really suitable masking strategy or suboptimal masking generation.\n" ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%% md\n" } } }, { "cell_type": "code", - "execution_count": 16, - "outputs": [ - { - "data": { - "text/plain": "array([[ 0.99129489, 1. , -0.97170838, -0.88683351, -1. ,\n -0.96517954, -0.9390642 , -0.90424374, -0.92600653, -0.96300326,\n -0.95429815, -0.9695321 , -0.97388466, -0.97606094, -0.90206746,\n -0.96300326, -0.9695321 , -0.94776931, -0.94994559, -0.96735582,\n -0.91730141, -0.92165397, -0.95647443, -0.9390642 , -0.97606094,\n -0.96300326, -0.97170838, -0.9085963 ]])" - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" + "execution_count": null, + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n", + "is_executing": true } - ], + }, + "outputs": [], "source": [ - "def normalize(data):\n", - " \"\"\"Squash all values into [-1,1] range.\"\"\"\n", - " zero_to_one = (data - np.min(data)) / (np.max(data) - np.min(data))\n", - " return 2*zero_to_one -1\n", - "saliency_map = normalize(explanation[0])\n", - "saliency_map.T" - ], + "# onnx model available on surf drive\n", + "# path to ONNX model\n", + "onnx_file = 'models/season_prediction_model_temp_max_binary.onnx'\n", + "\n", + "# verify the ONNX model is valid\n", + "onnx_model = onnx.load(onnx_file)\n", + "onnx.checker.check_model(onnx_model)\n", + "\n", + "def run_model(data):\n", + " # model must receive input in the order of [batch, timeseries, channels]\n", + " # data = data.transpose([0,2,1])\n", + " # get ONNX predictions\n", + " sess = ort.InferenceSession(onnx_file)\n", + " input_name = sess.get_inputs()[0].name\n", + " output_name = sess.get_outputs()[0].name\n", + "\n", + " onnx_input = {input_name: data.astype(np.float32)}\n", + " pred_onnx = sess.run([output_name], onnx_input)[0]\n", + " \n", + " return pred_onnx" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select an instance to explain and check the prediction with the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%%\n", + "is_executing": true } - } + }, + "outputs": [], + "source": [ + "idx = 6 # explained instance\n", + "data_instance = data_test[idx][np.newaxis, ...]\n", + "# precheck ONNX predictions\n", + "pred_onnx = run_model(data_instance)\n", + "pred_class = classes[np.argmax(pred_onnx)]\n", + "print(\"The predicted class is:\", pred_class)\n", + "print(\"The actual class is:\", classes[np.argmax(target_test.iloc[idx])])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 5 - Compute and visualize the relevance scores\n", + "In this section we compute the relevance scores for each segment of timeseries using RISE and visualize them on the original timeseries." + ] }, { "cell_type": "code", - "execution_count": 17, - "outputs": [ - { - "data": { - "text/plain": "
", - "image/png": "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WrdujVmzZuHdd99Fhw4dEBgYiLfffhv+/v4YM2aMeJVuALVdB09PTyxcuBBjx46FSqXC5cuXMWfOHAQFBSEyMlLEWtevGTNmYPPmzfj+++/h6upq6Pfj5uYGZ2dnuLm5YcqUKYiJiYGnpyeUSiVmzpyJsLAw9OvXT+Ta15/7XYfLly9j8+bNGDlyJFq0aIGTJ09i9uzZeOihh9CjRw+Ra082T+xha03dp59+KrRu3VpwdHQU+vbtKxw6dEjsKjWqp59+WvDz8xMcHR2Fli1bCk8//bRw6dIlsavVoH755RcBQJVl4sSJgiBUDKF/++23BV9fX8HJyUkIDw8XUlNTxa10A6jtOhQVFQnDhw8XvL29BQcHB6FNmzbC1KlTBbVaLXa161V15w9AWLdunWGbO3fuCC+//LLg4eEhuLi4CI899piQkZEhXqUbwP2uQ3p6uvDQQw8Jnp6egpOTkxAUFCS88cYbQl5enrgVJxIEQSYIgtCYgRcRERGRVLCPEBEREdksBkJERERksxgIERERkc1iIEREREQ2i4EQERER2SwGQkRERGSzGAgRERGRzWIgRERERDaLgRARERHZLAZCREREZLMYCBHZkJs3b0KlUuH99983rDt48CAcHR2NnpBORGQr+KwxIhvz008/YcyYMTh48CA6duyI4OBgjB49GkuXLhW7akREjY6BEJENmjFjBvbu3YvevXvj1KlTOHr0KJycnMSuFhFRo2MgRGSD7ty5g27duuHq1atITk5G9+7dxa4SEZEo2EeIyAZdvnwZN27cgE6nw5UrV8SuDhGRaJgRIrIxWq0Wffv2RXBwMDp27Ijly5fj1KlT8PHxEbtqRESNjoEQkY154403sH37dpw4cQLNmzfH4MGD4ebmhl27doldNSKiRsemMSIbkpiYiOXLl+O///0vlEol5HI5/vvf/+LXX3/FqlWrxK4eEVGjY0aIiIiIbBYzQkRERGSzGAgRERGRzWIgRERERDaLgRARERHZLAZCREREZLMYCBEREZHNYiBERERENouBEBEREdksBkJERERksxgIERERkc1iIEREREQ2i4EQERER2az/Dx8dm0ay7vAcAAAAAElFTkSuQmCC\n" - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": "" - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" + "execution_count": null, + "metadata": { + "pycharm": { + "is_executing": true } - ], + }, + "outputs": [], "source": [ - "from dianna import visualization\n", - "heatmap_channel = normalize(explanation[0])\n", + "# call the explainer\n", + "explanation = dianna.explain_timeseries(run_model, timeseries_data=data_instance[0],\n", + " method='rise', labels=[0,1], p_keep=0.1,\n", + " n_masks=10000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can visualize the relevance scores on top of the displayed timeseries using the visualization tool in dianna." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n", + "is_executing": true + } + }, + "outputs": [], + "source": [ + "heatmap_channel = normalize(explanation[np.argmax(pred_onnx)])\n", "segments = []\n", "for i in range(len(heatmap_channel) - 1):\n", " segments.append({\n", @@ -1783,21 +767,34 @@ " 'start': i - 0.5,\n", " 'stop': i + 0.5,\n", " 'weight': heatmap_channel[i]})\n", - "visualization.plot_timeseries(range(len(heatmap_channel)), input_image, segments, show_plot=True)\n" - ], + "visualization.plot_timeseries(range(len(heatmap_channel)), data_instance[0],\n", + " segments, xlabel=\"Time index\", ylabel=\"Temperature\",\n", + " show_plot=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", "metadata": { - "collapsed": false, "pycharm": { - "name": "#%%\n" + "name": "#%% md\n" } - } + }, + "source": [ + "#### 6 - Conclusions\n", + "The relevance scores are generated by passing multiple randomly masked inputs to the black-box model and averaging their segment-wise relevances. The idea behind this is that whenever a mask preserves important parts of the timeseries it gets higher score.
\n", + "\n", + "The first example with a designed timeseries and an expert model demonstrates that RISE is able to identify the important segments for classification in this simplified case.\n", + "\n", + "The second example shows that RISE for timeseries also runs on real timeseries data. The explanation is, however, hard to interpret in this case. This could be due to an suboptimally trained model, unsuitable masking strategy or unsuitable mask generation.\n" + ] } ], "metadata": { "kernelspec": { - "name": "python3", + "display_name": "torch", "language": "python", - "display_name": "Python 3 (ipykernel)" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -1809,11 +806,11 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.10.8" }, "vscode": { "interpreter": { - "hash": "951e587de391aa2bb289e8fbd39b65d4ffaa4789dc01c18d4fc05216cb0e7d1f" + "hash": "f74811edbe99894b2f930b63702daebe3ce5897f538d47d6f6827e4475af2be0" } } },