From e750a234fbb162325815e1facbb3f7851840715d Mon Sep 17 00:00:00 2001 From: sinavidi95 Date: Tue, 23 Sep 2025 23:58:14 -0400 Subject: [PATCH 1/3] Fix the url as a string in loading data! --- examples/01_featureset_basics.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/01_featureset_basics.ipynb b/examples/01_featureset_basics.ipynb index 77666ff..511584b 100644 --- a/examples/01_featureset_basics.ipynb +++ b/examples/01_featureset_basics.ipynb @@ -50,7 +50,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "669a024e", "metadata": {}, "outputs": [ @@ -72,7 +72,7 @@ "\n", "import modularml as mml\n", "\n", - "DATA_URL = Path(\"https://raw.githubusercontent.com/REIL-UConn/fine-tuning-for-rapid-soh-estimation/main/processed_data/UConn-ILCC-NMC/data_slowpulse_1.pkl\")\n", + "DATA_URL = \"https://raw.githubusercontent.com/REIL-UConn/fine-tuning-for-rapid-soh-estimation/main/processed_data/UConn-ILCC-NMC/data_slowpulse_1.pkl\"\n", "DATA_DIR = Path(\"downloaded_data\")\n", "DATA_PATH = DATA_DIR / \"data_slowpulse_1.pkl\"\n", "DATA_DIR.mkdir(exist_ok=True, parents=True)\n", From a4ebe1fa8d4fd12dc226fe93767b272bf26d883b Mon Sep 17 00:00:00 2001 From: sinavidi95 Date: Wed, 24 Sep 2025 14:32:53 -0400 Subject: [PATCH 2/3] Add Feature Importance analysis example! --- examples/04_feature_importance.ipynb | 685 +++++++++++++++++++++++++++ 1 file changed, 685 insertions(+) create mode 100644 examples/04_feature_importance.ipynb diff --git a/examples/04_feature_importance.ipynb b/examples/04_feature_importance.ipynb new file mode 100644 index 0000000..4dbc765 --- /dev/null +++ b/examples/04_feature_importance.ipynb @@ -0,0 +1,685 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "3772275a", + "metadata": {}, + "source": [ + "---\n", + "# 04_featureset_importance.ipynb\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "3c42e4df", + "metadata": {}, + "source": [ + "## Introduction: What is Feature Importance Analysis?\n", + "\n", + "**Feature importance analysis** helps reveal how different inputs affect model predictions.\n", + "\n", + "It is useful for:\n", + "\n", + "* **Interpretability** – seeing which variables drive outcomes.\n", + "* **Diagnostics** – identifying redundant or weak features that may add noise.\n", + "* **Domain insights** – revealing which physical, statistical, or operational descriptors are most relevant for the task\n", + "\n", + "We focus on two main approaches:\n", + "\n", + "* **Model-based**: importance derived from model internals (e.g., tree importances, coefficients).\n", + "* **Perturbation-based**: measuring prediction changes when features are shuffled or masked.\n", + "\n", + "In this notebook, we’ll show how to:\n", + "\n", + "* Extract statistical features from battery voltage data.\n", + "* Evaluate and visualize feature importance to understand which features contribute most.\n" + ] + }, + { + "cell_type": "markdown", + "id": "8611971a", + "metadata": {}, + "source": [ + "## Step 1: Loading Example Data\n", + "\n", + "We begin by downloading an example dataset from our battery health estimation paper: “Fine-tuning for rapid capacity estimation of lithium-ion batteries” ([10.1016/j.ensm.2025.104425](https://doi.org/10.1016/j.ensm.2025.104425)).\n", + "This dataset contains time-series voltage responses to 100-second DC pulses collected across the life of several lithium-ion cells.\n", + "More information on the dataset and usage can be found on the following GitHub repository: [REIL-UConn/fine-tuning-for-rapid-soh-estimation]{https://github.com/REIL-UConn/fine-tuning-for-rapid-soh-estimation.git}.\n", + "\n", + "\n", + "We'll download and load the data from GitHub. \n", + "The file is a `.pkl` (pickled Python object) containing a dictionary of key-value arrays." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "669a024e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading data...\n", + "Download complete.\n", + "Available keys: ['cell_id', 'group_id', 'rpt', 'num_cycles', 'soc', 'soc - coulomb', 'pulse_type', 'voltage', 'q_dchg', 'soh', 'dcir_chg_10', 'dcir_dchg_10', 'dcir_chg_20', 'dcir_dchg_20', 'dcir_chg_30', 'dcir_dchg_30', 'dcir_chg_40', 'dcir_dchg_40', 'dcir_chg_50', 'dcir_dchg_50', 'dcir_chg_60', 'dcir_dchg_60', 'dcir_chg_70', 'dcir_dchg_70', 'dcir_chg_80', 'dcir_dchg_80', 'dcir_chg_90', 'dcir_dchg_90']\n", + "Total number of samples: 24048\n" + ] + } + ], + "source": [ + "import pickle\n", + "import urllib.request\n", + "import warnings\n", + "from pathlib import Path\n", + "import modularml as mml\n", + "\n", + "DATA_URL = \"https://raw.githubusercontent.com/REIL-UConn/fine-tuning-for-rapid-soh-estimation/main/processed_data/UConn-ILCC-NMC/data_slowpulse_1.pkl\"\n", + "DATA_DIR = Path(\"downloaded_data\")\n", + "DATA_PATH = DATA_DIR / \"data_slowpulse_1.pkl\"\n", + "DATA_DIR.mkdir(exist_ok=True, parents=True)\n", + "\n", + "if not DATA_PATH.exists():\n", + " print(\"Downloading data...\")\n", + " urllib.request.urlretrieve(url=DATA_URL, filename=DATA_PATH)\n", + " print(\"Download complete.\")\n", + "else:\n", + " print(\"Data already downloaded.\")\n", + "\n", + "with warnings.catch_warnings():\n", + " warnings.simplefilter(\"ignore\", category=DeprecationWarning)\n", + " data = pickle.load(Path.open(DATA_PATH, \"rb\"))\n", + "\n", + "print(f\"Available keys: {list(data.keys())}\")\n", + "print(f\"Total number of samples: {len(data[next(iter(data.keys()))])}\")" + ] + }, + { + "cell_type": "markdown", + "id": "65a72afc", + "metadata": {}, + "source": [ + "## Step 2: Understanding the Data Format\n", + "\n", + "Our data is structured as a dictionary, where each key corresponds to a signal or property:\n", + "* `voltage`: the time-series voltage response during a 100-second pulse (shape: [n_samples, 101])\n", + "* `soh`: state-of-health, a float between ~0.5 and 1.0\n", + "* `cell_id`, `group_id`, `pulse_type`, `soc`: metadata about the sample\n" + ] + }, + { + "cell_type": "markdown", + "id": "bfce70c3", + "metadata": {}, + "source": [ + "## Step 3: Creating a raw FeatureSet\n", + "\n", + "To create a `FeatureSet`, we use the `from_dict()` constructor. \n", + "We must assign a `label`, which uniquely identifies this `FeatureSet` within the broader modeling pipeline (e.g., when connecting to model stages)." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "33cd6f32", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "FeatureSet(label='PulseFeaturesRaw', n_samples=24048)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from modularml.core import FeatureSet\n", + "\n", + "fs_raw = FeatureSet.from_dict(\n", + " label=\"PulseFeaturesRaw\",\n", + " data={\n", + " \"voltage\": data[\"voltage\"],\n", + " \"soh\": data[\"soh\"],\n", + " \"cell_id\": data[\"cell_id\"],\n", + " \"group_id\": data[\"group_id\"],\n", + " \"pulse_type\": data[\"pulse_type\"],\n", + " \"pulse_soc\": data[\"soc\"],\n", + " },\n", + " feature_keys=\"voltage\",\n", + " target_keys=\"soh\",\n", + " tag_keys=[\"cell_id\", \"group_id\", \"pulse_type\", \"pulse_soc\"],\n", + ")\n", + "fs_raw\n" + ] + }, + { + "cell_type": "markdown", + "id": "05cd3631", + "metadata": {}, + "source": [ + "## Step 3: Derive statistical features from voltage and create a new FeatureSet" + ] + }, + { + "cell_type": "markdown", + "id": "0afbd3a5", + "metadata": {}, + "source": [ + "Helper function: stats on a 1D array-like" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f684ae3f", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "def voltage_stats_1d(x):\n", + " arr = np.asarray(x, dtype=float).ravel()\n", + " arr = arr[~np.isnan(arr)]\n", + " if arr.size == 0:\n", + " return dict(v_min=np.nan, v_max=np.nan, v_mean=np.nan, v_var=np.nan, v_skew=np.nan, v_kurt=np.nan)\n", + " v_min = float(np.min(arr))\n", + " v_max = float(np.max(arr))\n", + " v_mean = float(np.mean(arr))\n", + " v_var = float(np.var(arr, ddof=1)) if arr.size > 1 else 0.0\n", + " try:\n", + " from scipy.stats import skew, kurtosis\n", + " v_skew = float(skew(arr, bias=False)) if arr.size > 2 else 0.0\n", + " v_kurt = float(kurtosis(arr, fisher=True, bias=False)) if arr.size > 3 else 0.0\n", + " except Exception:\n", + " s = pd.Series(arr)\n", + " v_skew = float(s.skew()) if arr.size > 2 else 0.0\n", + " v_kurt = float(s.kurt()) if arr.size > 3 else 0.0\n", + " return dict(v_min=v_min, v_max=v_max, v_mean=v_mean, v_var=v_var, v_skew=v_skew, v_kurt=v_kurt)\n" + ] + }, + { + "cell_type": "markdown", + "id": "d5fa6b2d", + "metadata": {}, + "source": [ + "Grab the voltage sequences from fs_raw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c698d1c7", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " voltages = fs_raw.data[\"voltage\"] \n", + "except Exception:\n", + " voltages = data[\"voltage\"] " + ] + }, + { + "cell_type": "markdown", + "id": "26849eae", + "metadata": {}, + "source": [ + "Compute stats row-wise" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "3ae08ab9", + "metadata": {}, + "outputs": [], + "source": [ + "stats_list = [voltage_stats_1d(v) for v in voltages]\n", + "stats_df = pd.DataFrame(stats_list)" + ] + }, + { + "cell_type": "markdown", + "id": "bba30b6b", + "metadata": {}, + "source": [ + "Build the stats FeatureSet for modeling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "504b4b66", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "FeatureSet(label='PulseFeaturesStats', n_samples=24048)" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "base_df = pd.DataFrame({\n", + " \"soh\": data[\"soh\"],\n", + " \"cell_id\": data[\"cell_id\"],\n", + " \"group_id\": data[\"group_id\"],\n", + " \"pulse_type\": data[\"pulse_type\"],\n", + " \"pulse_soc\": data[\"soc\"],\n", + " })\n", + "df_stats = pd.concat([base_df.reset_index(drop=True), stats_df.reset_index(drop=True)], axis=1)\n", + "\n", + "\n", + "def to_np_str_series(s):\n", + " # elementwise cast guarantees each item is np.str_ \n", + " return np.array([np.str_(x) for x in s.values], dtype=np.str_)\n", + "\n", + "feat_cols = [\"v_min\",\"v_max\",\"v_mean\",\"v_var\",\"v_skew\",\"v_kurt\"]\n", + "target = \"soh\"\n", + "\n", + "data_dict = {\n", + " # features\n", + " \"v_min\": df_stats[\"v_min\"].to_numpy(),\n", + " \"v_max\": df_stats[\"v_max\"].to_numpy(),\n", + " \"v_mean\": df_stats[\"v_mean\"].to_numpy(),\n", + " \"v_var\": df_stats[\"v_var\"].to_numpy(),\n", + " \"v_skew\": df_stats[\"v_skew\"].to_numpy(),\n", + " \"v_kurt\": df_stats[\"v_kurt\"].to_numpy(),\n", + " # target\n", + " \"soh\": df_stats[\"soh\"].to_numpy(),\n", + " # tags — force NumPy string scalars where needed\n", + " \"cell_id\": to_np_str_series(df_stats[\"cell_id\"]),\n", + " \"group_id\": df_stats[\"group_id\"].to_numpy(), \n", + " \"pulse_type\": to_np_str_series(df_stats[\"pulse_type\"]),\n", + " \"pulse_soc\": df_stats[\"pulse_soc\"].to_numpy(),\n", + "}\n", + "\n", + "fs_stats = FeatureSet.from_dict(\n", + " label=\"PulseFeaturesStats\",\n", + " data=data_dict,\n", + " feature_keys=feat_cols,\n", + " target_keys=target,\n", + " tag_keys=[\"cell_id\",\"group_id\",\"pulse_type\",\"pulse_soc\"],\n", + ")\n", + "fs_stats" + ] + }, + { + "cell_type": "markdown", + "id": "9ca151a6", + "metadata": {}, + "source": [ + "#### Filtering charge samples\n", + "\n", + "The `.filter` method takes keyword arguments, where keys can correspond to any attribute of the samples' tags, features, or targets." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "da7d6952", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FeatureSet(label='filtered', n_samples=12024)\n", + "Filtered to 12024 charge-only samples.\n" + ] + } + ], + "source": [ + "charge_samples = fs_stats.filter(pulse_type=\"chg\")\n", + "print(charge_samples)\n", + "print(f\"Filtered to {len(charge_samples.samples)} charge-only samples.\")" + ] + }, + { + "cell_type": "markdown", + "id": "27050472", + "metadata": {}, + "source": [ + "Note that the `.filter` method returns a new `FeatureSet` containing copies of the filtered samples.\n", + "\n", + "By default, it is returned with a label of `'filtered'`, but we can set a new label with `.set_label`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "b609296b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FeatureSet(label='ChargePulseFeatures', n_samples=12024)\n" + ] + } + ], + "source": [ + "charge_samples.label = \"ChargePulseFeatures\"\n", + "print(charge_samples)" + ] + }, + { + "cell_type": "markdown", + "id": "b5dab074", + "metadata": {}, + "source": [ + "## Step 4: Running feature importance\n", + "Using both model-based (Random Forest) and perturbation-based (permutation) importance\n" + ] + }, + { + "cell_type": "markdown", + "id": "dfc72e72", + "metadata": {}, + "source": [ + "1) Setup: imports and reproducible config" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "663d0904", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "from sklearn.ensemble import RandomForestRegressor\n", + "from sklearn.model_selection import GroupShuffleSplit\n", + "from sklearn.inspection import permutation_importance\n", + "\n", + "RANDOM_STATE = 42\n", + "feat_cols = [\"v_min\",\"v_max\",\"v_mean\",\"v_var\",\"v_skew\",\"v_kurt\"]\n", + "target_col = \"soh\"\n", + "group_tag = \"group_id\" \n" + ] + }, + { + "cell_type": "markdown", + "id": "b1cd79f2", + "metadata": {}, + "source": [ + "2) Build X, y, and group labels from FeatureSet" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce092a6b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(12024, 6) (12024,) (12024,)\n" + ] + } + ], + "source": [ + "def _scalar(x):\n", + " arr = np.asarray(x).ravel()\n", + " return float(arr[0]) if arr.size else np.nan\n", + "\n", + "def arrays_from_featureset(fs, feature_keys, target_key, group_key):\n", + " X_list, y_list, g_list = [], [], []\n", + " for s in fs.samples:\n", + " # build one feature row\n", + " row = []\n", + " bad = False\n", + " for k in feature_keys:\n", + " v = _scalar(s.features[k].value)\n", + " if not np.isfinite(v):\n", + " bad = True\n", + " break\n", + " row.append(v)\n", + " if bad:\n", + " continue\n", + "\n", + " # target\n", + " yv = _scalar(s.targets[target_key].value)\n", + " if not np.isfinite(yv):\n", + " continue\n", + "\n", + " # group label \n", + " gv = s.tags[group_key].value\n", + " g_list.append(gv)\n", + " y_list.append(yv)\n", + " X_list.append(row)\n", + "\n", + " X = np.asarray(X_list, dtype=float)\n", + " y = np.asarray(y_list, dtype=float)\n", + " groups = np.asarray(g_list)\n", + " return X, y, groups\n", + "\n", + "# Build arrays from the filtered FeatureSet\n", + "X, y, groups = arrays_from_featureset(charge_samples, feat_cols, target_col, group_tag)\n", + "print(X.shape, y.shape, groups.shape)\n" + ] + }, + { + "cell_type": "markdown", + "id": "6f9af99a", + "metadata": {}, + "source": [ + "3) Group-aware train/test split" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "7329af50", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(9234, 6) (9234,)\n", + "(2790, 6) (2790,)\n" + ] + } + ], + "source": [ + "gss = GroupShuffleSplit(n_splits=1, test_size=0.2, random_state=RANDOM_STATE)\n", + "(train_idx, test_idx), = gss.split(X, groups=groups)\n", + "\n", + "X_tr, X_te = X[train_idx], X[test_idx]\n", + "y_tr, y_te = y[train_idx], y[test_idx]\n", + "\n", + "print(X_tr.shape, y_tr.shape)\n", + "print(X_te.shape, y_te.shape)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "26a39387", + "metadata": {}, + "source": [ + "4) Fit baseline Random Forest regressor" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "accd1e1d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test R^2: 0.961\n" + ] + } + ], + "source": [ + "rf = RandomForestRegressor(\n", + " n_estimators=400,\n", + " random_state=RANDOM_STATE,\n", + " n_jobs=-1\n", + ")\n", + "rf.fit(X_tr, y_tr)\n", + "print(f\"Test R^2: {rf.score(X_te, y_te):.3f}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "1be929ac", + "metadata": {}, + "source": [ + "5) Compute feature importances (model-based + permutation)" + ] + }, + { + "cell_type": "markdown", + "id": "a915ddd5", + "metadata": {}, + "source": [ + "**Model-based importance** computed from the average reduction in MSE each feature provides across all splits and trees. Larger values mean the feature is frequently used in informative splits (often near the top of trees)." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "d7ccc2af", + "metadata": {}, + "outputs": [], + "source": [ + "# (a) Model-based\n", + "imp_model = rf.feature_importances_\n", + "order = np.argsort(imp_model)[::-1]\n", + "feat_order = [feat_cols[i] for i in order]\n", + "imp_model_sorted = imp_model[order]" + ] + }, + { + "cell_type": "markdown", + "id": "f68d3f1a", + "metadata": {}, + "source": [ + "**Permutation-based importance** measures how much test performance drops when we randomly shuffle one feature at a time (breaking its relationship to the target). The bar height is the mean drop across repeats; the error bars show variability across shuffles." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "31db3e8b", + "metadata": {}, + "outputs": [], + "source": [ + "# (b) Permutation-based (on held-out test)\n", + "perm = permutation_importance(\n", + " rf, X_te, y_te,\n", + " n_repeats=20,\n", + " random_state=RANDOM_STATE,\n", + " n_jobs=-1\n", + ")\n", + "imp_perm_mean = perm.importances_mean[order]\n", + "imp_perm_std = perm.importances_std[order]" + ] + }, + { + "cell_type": "markdown", + "id": "744103cb", + "metadata": {}, + "source": [ + "6) Plot feature importance" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "57dffc0a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAGGCAYAAACNCg6xAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAQ3FJREFUeJzt3QucTfX+//GP+yW5TkzJSaVyv0QklS6kk4quuo4UleimOhERlWvHIRy6qROnKKXL0dFFFHGSkUhRKrdikBiRS6z/4/39/de29549rBkzs2dmv56Px2L22mvv/d3fvfZen/X9fr7fVcTzPM8AAABwWEUPvwkAAACEwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQDyyLp166x06dL22WefxbsoNmfOHCtSpIj7P6teeukl99jVq1cfdltt17NnTytIYr2/M8880/72t7/FtVzIHwicUCj4P3Sxlt69e+fKa86fP98ee+wx27Ztm+XX+li0aJEVVP/85z/d+yhMBg0aZC1atLBWrVqF1t1yyy3usypfvrz98ccfGR7z/fffh/blp556Ko9LDN/DDz9s48aNs40bN8a7KIiz4vEuAJDTB6YTTzwxYl39+vVzLXAaOHCgO/BVrFgxV14jkSlwSkpKcvVbGGzevNn+9a9/uSVa8eLFbdeuXfbuu+/atddeG3Hfv//9b9dKtXv37jwsLaJ16NDBBbfaL/U7g8RF4IRC5a9//as1a9bMCrKdO3faUUcdZYlKAUTZsmWtsJk8ebILkC677LIM95UqVcq1Qr366qsZAqdXXnnF2rdvb2+88UYelhbRihYtaldffbW9/PLL7oRJLYBITHTVIaH897//tXPOOccFJkcffbQ7IC1fvjxim6VLl7pWjpNOOsmd6ScnJ9utt95qv/76a2gbddE99NBD7m+1cPldKcqJ0KK/Y3Uzab0eG/48WvfNN9/YDTfcYJUqVbKzzz474mDbtGlTK1OmjFWuXNmuu+46lyeTHXpP5cqVs7Vr19qll17q/q5evbrrfpBly5bZBRdc4OrmhBNOcAfsWN1/n376qd1xxx1WpUoVdwaekpJiv/32W4bX05l5vXr1XFBw3HHHWY8ePTJ0a5533nmuRTA1NdXOPfdcFzA98sgjVrNmTfe5fPLJJ6G61baydetWe/DBB61BgwbuPagMCpi/+uqrmDk8r732mj355JN2/PHHu8/zwgsvtFWrVmUo7+eff26XXHKJ+wxUBw0bNrTRo0dHbLNixQp38NRnoedSkP7OO+8Eqv+33nrLddOpzLHo89f+GV5HX3zxheuq032x/Pjjj3bNNde48qjulIczY8aMDNutX7/eOnbs6N5X1apV7f7777c9e/bEfE7Vw8UXX2wVKlRwz9m6descyclSy9lpp53m6k37tPajcGvWrLG77rrLbaP9XfuX3lt0HtW+fftc4HLKKae459J2+s58+OGH2fqstJ9pv9drah954okn7MCBAzHfQ9u2bV05lyxZcsT1gYKLFicUKtu3b7ctW7ZErFN3j0yaNMk6d+5s7dq1s2HDhrmWjfHjx7sf3S+//NIdrEU/wDogdenSxQVN+mF99tln3f//+9//3MH4yiuvtO+++861EPzjH/8IvcYxxxzjumSySgcIHQgGDx5snue5dTrYP/roo64FomvXru55x4wZ4wIMlTc73YP79+93QYaeY/jw4e5gpsRdHVD79u1rN954o3tvEyZMcAFRy5YtM3R9anu9toK+lStXujrUwcQPVET36eDWpk0b6969e2g7BQI6CJcoUSL0fApIVSYFhTfddJNVq1bNBUl33323CzJULtF60WejIER1prKlpaXZM8884w7wCkAVpIUbOnSoay1QsKX9Q+9b71MBgk+fuYLJY4891u699173uX/77bf2n//8x90Wff5qFVKwqbw51ZmCMgUkag264oorMq13Hez13lUXmVG933nnnfbmm2+6QF0UvNauXdtOP/30DNvrfZ911lluP77nnntcAKFuwMsvv9ymTZsWKo/yphQsKmDWdqoffRc+/vjjDM+pdfosFNgMGDDA1duLL77oAou5c+da8+bNLTsUAE+dOtW9vgJpBdUKzhYuXBjqSlf9qPtb+4ECGAVM2me0L+hz9VshtW8NGTLEfSdUnvT0dJfLt3jxYhfYZOWzUr7S+eefb3/++WdoO33XFUTFonoR7cNNmjTJVl2gEPCAQuDFF19UtBFzkR07dngVK1b0unXrFvG4jRs3ehUqVIhYv2vXrgzP/+qrr7rn+vTTT0PrRowY4db99NNPEdvqttarTNG0fsCAAaHb+lvrrr/++ojtVq9e7RUrVsx78sknI9YvW7bM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1NLkV86hLnsAAAASQ3p6umtU8WOEQ0m4wMnvnlPQROAEAAB8QVJ4SA4HAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICAEu5adXmhZu8ZluhWD20f7yIAAFA4W5zGjRtnNWvWtNKlS1uLFi1s4cKFmW573nnnuYvwRS/t23OgBgAAhTxwmjp1qvXq1csGDBhgixcvtkaNGlm7du1s06ZNMbd/8803bcOGDaHl66+/tmLFitk111yT52UHAACJJe6B08iRI61bt27WpUsXq1u3rk2YMMHKli1rEydOjLl95cqVLTk5ObR8+OGHbnsCJwAAUKgDp71791pqaqq1adPmYIGKFnW3FyxYEOg5XnjhBbvuuuvsqKOOinn/nj17LD09PWIBAAAocIHTli1bbP/+/VatWrWI9bq9cePGwz5euVDqquvatWum2wwZMsQqVKgQWmrUqJEjZQcAAIkn7l11R0KtTQ0aNLDmzZtnuk2fPn1s+/btoWXdunV5WkYAAFB4xHU6gqSkJJfYnZaWFrFet5W/dCg7d+60KVOm2KBBgw65XalSpdwCAABQoFucSpYsaU2bNrVZs2aF1h04cMDdbtmy5SEf+/rrr7v8pZtuuikPSgoAAJAPJsDUVASdO3e2Zs2auS63UaNGudYkjbKTlJQUq169ustViu6m69ixo1WpUiVOJQcAAIkm7oFTp06dbPPmzda/f3+XEN64cWObOXNmKGF87dq1bqRduJUrV9q8efPsgw8+iFOpAQBAIirieZ5nCUTTEWh0nRLFy5cvnyuvwSVXuOQKAKBwxgYFelQdAABAXiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAoKAETuPGjbOaNWta6dKlrUWLFrZw4cJDbr9t2zbr0aOHHXvssVaqVCk79dRT7b333suz8gIAgMRVPJ4vPnXqVOvVq5dNmDDBBU2jRo2ydu3a2cqVK61q1aoZtt+7d6+1bdvW3Tdt2jSrXr26rVmzxipWrBiX8gMAgMQS18Bp5MiR1q1bN+vSpYu7rQBqxowZNnHiROvdu3eG7bV+69atNn/+fCtRooRbp9YqAACAQt1Vp9aj1NRUa9OmzcHCFC3qbi9YsCDmY9555x1r2bKl66qrVq2a1a9f3wYPHmz79+/Pw5IDAIBEFbcWpy1btriARwFQON1esWJFzMf8+OOP9vHHH9uNN97o8ppWrVpld911l+3bt88GDBgQ8zF79uxxiy89PT2H3wkAAEgUcU8Oz4oDBw64/KZnn33WmjZtap06dbK+ffu6Lr7MDBkyxCpUqBBaatSokadlBgAAhUfcAqekpCQrVqyYpaWlRazX7eTk5JiP0Ug6jaLT43x16tSxjRs3uq6/WPr06WPbt28PLevWrcvhdwIAABJF3AKnkiVLulajWbNmRbQo6bbymGJp1aqV657Tdr7vvvvOBVR6vlg0ZUH58uUjFgAAgALXVaepCJ577jn717/+Zd9++611797ddu7cGRpll5KS4lqMfLpfo+ruvfdeFzBpBJ6Sw5UsDgAAUKinI1CO0ubNm61///6uu61x48Y2c+bMUML42rVr3Ug7n/KT3n//fbv//vutYcOGbh4nBVEPP/xwHN8FAABIFEU8z/MsgWhUnZLEle+UW912NXvPsES3emj7eBcBAIAcjw0K1Kg6AACAeCJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIIUOI0bN85q1qxppUuXthYtWtjChQsz3fall16yIkWKRCx6HAAAQKEPnKZOnWq9evWyAQMG2OLFi61Ro0bWrl0727RpU6aPKV++vG3YsCG0rFmzJk/LDAAAElPcA6eRI0dat27drEuXLla3bl2bMGGClS1b1iZOnJjpY9TKlJycHFqqVauWp2UGAACJKa6B0969ey01NdXatGlzsEBFi7rbCxYsyPRxv//+u51wwglWo0YN69Chgy1fvjyPSgwAABJZXAOnLVu22P79+zO0GOn2xo0bYz7mtNNOc61Rb7/9tk2ePNkOHDhgZ511lq1fvz7m9nv27LH09PSIBQAAoEB21WVVy5YtLSUlxRo3bmytW7e2N99804455hh75plnYm4/ZMgQq1ChQmhRKxUAAECBC5ySkpKsWLFilpaWFrFet5W7FESJEiWsSZMmtmrVqpj39+nTx7Zv3x5a1q1blyNlBwAAiSeugVPJkiWtadOmNmvWrNA6db3ptlqWglBX37Jly+zYY4+NeX+pUqXcKLzwBQAAIDuKW5xpKoLOnTtbs2bNrHnz5jZq1CjbuXOnG2Un6parXr2663KTQYMG2Zlnnmm1atWybdu22YgRI9x0BF27do3zOwEAAIVd3AOnTp062ebNm61///4uIVy5SzNnzgwljK9du9aNtPP99ttvbvoCbVupUiXXYjV//nw3lQEAAEBuKuJ5nmcJRKPqlCSufKfc6rar2XuGJbrVQ9vHuwgAAOR4bFDgRtUBAADEC4ETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQG4HTpMmTbJWrVrZcccd5yagFE1eqYvvAgAAFEbZCpzGjx/vZvy+5JJL3OzduuyJVKxY0QVPAAAAhVG2AqcxY8bYc889Z3379nUX6fXpsim6bhwAAEBhlK3A6aeffrImTZrEvKCurjMHAABQGGUrcDrxxBNtyZIlGdbrGnN16tTJiXIBAAAUjov8Kr+pR48etnv3btOl7hYuXGivvvqqDRkyxJ5//vmcLyUAAEBBDZy6du1qZcqUsX79+tmuXbvshhtucKPrRo8ebdddd13OlxIAAKCgBk5y4403ukWB0++//25Vq1bN2ZIBAAAUhsBJyeF//vmnnXLKKVa2bFm3yPfff28lSpSwmjVr5nQ5AQAACmZy+C233GLz58/PsP7zzz939wEAABRG2QqcvvzySzdreLQzzzwz5mg7AACAhA2cihQpYjt27Miwfvv27aFZxAEAAAqbbAVO5557rpt6IDxI0t9ad/bZZ+dk+QAAAAp2cviwYcNc8HTaaafZOeec49bNnTvX0tPT7eOPP87pMgIAABTcFqe6deva0qVL7dprr7VNmza5bruUlBRbsWKF1a9fP+dLCQAAUJDncdKEl4MHD87Z0gAAABTGwGnbtm3uUitqcTpw4EDEfWp9AgAAKGyyFTi9++67btZwzRhevnx5N8rOp78JnAAAQGGUrRynBx54wG699VYXOKnl6bfffgstW7duzflSAgAAFNTA6eeff7Z77rkndKkVAACARJCtwKldu3a2aNGinC8NAABAYctxat++vT300EP2zTffWIMGDdyFfcNdfvnlOVU+AACAgh04devWzf0/aNCgDPcpOTyrl10ZN26cjRgxwjZu3GiNGjWyMWPGWPPmzQ/7uClTptj1119vHTp0sLfeeitLrwkAAJAnXXWafiCzJatB09SpU61Xr142YMAAW7x4sQuc1BWoaQ4OZfXq1fbggw+GZi4HAADIl4FTTho5cqRrwerSpYubkXzChAku6XzixImZPkbBmaZDGDhwoJ100kl5Wl4AAJC4sj0B5s6dO+2TTz6xtWvX2t69eyPu04i7IPS41NRU69OnT2hd0aJFrU2bNrZgwYJMH6cuwqpVq9ptt93mrpF3KHv27HGLT9fTAwAAyLPA6csvv7RLLrnEdu3a5QKoypUr25YtW1xLkQKaoIGTHqPWo2rVqkWs121d9y6WefPm2QsvvGBLliwJ9BpDhgxxLVMAAABx6aq7//777bLLLnMTXpYpU8b+97//2Zo1a6xp06b21FNPWW7RxYRvvvlme+655ywpKSnQY9SatX379tCybt26XCsfAAAo3LLV4qTWnmeeecZ1qxUrVsx1hSnXaPjw4da5c2e78sorAz2Pgh89Pi0tLWK9bicnJ2fY/ocffnBJ4QrafP518ooXL24rV660k08+OeIxpUqVcgsAAEBcWpw0b5OCJlHXnPKcpEKFCllq0SlZsqRrpZo1a1ZEIKTbLVu2zLB97dq1bdmyZS5w8xfNGXX++ee7v2vUqJGdtwMAAJB7LU5NmjSxL774wk455RRr3bq19e/f3+UrTZo0yerXr5+l59JUBGqlatasmZu7adSoUS5vSqPsRBcMrl69ustVKl26dIbnr1ixovs/q68LAACQJ4HT4MGDXb6RPPnkky646d69uwuklLidFZ06dbLNmze74EsTYDZu3NhmzpwZShhXa5bfugUAABBPRTzP8yyBaDoCdSkqUbx8+fK58ho1e8+wRLd6aPt4FwEAgByPDbLVlHPBBRfYtm3bYr6w7gMAACiMshU4zZkzJ8Okl7J79+7DTkgJAACQEDlOS5cuDf39zTffuJwknyayVG6SErkBAAAs0QMnJW4XKVLELbG65DQZ5pgxY3KyfAAAAAUzcPrpp59MueSa7HLhwoV2zDHHRMzJpDmdNKElAACAJXrgdMIJJ9i+ffvcvEtVqlRxtwEAABJF0ezMGj59+vTcKQ0AAEBhG1XXoUMHe+utt3K+NAAAAIVt5nDNED5o0CD77LPP3LXmjjrqqIj777nnnpwqHwAAQMEOnHRZFV0jLjU11S3hNOKOwAkAABRG2QqcNLoOAAAg0Rzx1XM1PUGCXe4OAAAkqGwHTi+//LI1aNDATXqppWHDhjZp0qScLR0AAEBB76obOXKkPfroo9azZ09r1aqVWzdv3jy78847bcuWLXb//ffndDkBAAAKZuCky6qMHz/eUlJSQusuv/xyq1evnj322GMETgAAoFDKVlfdhg0b7KyzzsqwXut0HwAAQGGUrcCpVq1a9tprr2VYP3XqVDfHEwAAQGGUra66gQMHWqdOnezTTz8N5ThpMsxZs2bFDKgAAAAStsXpqquuss8//9ySkpLcpVe06O+FCxfaFVdckfOlBAAAKKgtTqJLrUyePDlnSwMAAFAYA6f9+/fb9OnT7dtvv3W369at6y7+W7x4tp8SAAAgX8tWlLN8+XI3/cDGjRvttNNOc+uGDRtmxxxzjL377rtWv379nC4nAABAwcxx6tq1q5uzaf369bZ48WK3rFu3zs0efvvtt+d8KQEAAApqi9OSJUts0aJFVqlSpdA6/f3kk0/aGWeckZPlAwAAKNgtTqeeeqqlpaVlWL9p0yY3xxMAAEBhlK3AaciQIXbPPffYtGnTXHedFv193333uVyn9PT00AIAAJDQXXWXXnqp+//aa6+1IkWKuL89z3P/X3bZZaHbuk+j7wAAABI2cJo9e3aOFmLcuHE2YsQIN0qvUaNG7iLCzZs3j7ntm2++aYMHD7ZVq1bZvn373CVeHnjgAbv55ptztEwAAAA5Eji1bt3acoqub9erVy+bMGGCtWjRwkaNGmXt2rWzlStXWtWqVTNsX7lyZevbt6/Vrl3bSpYsaf/5z3+sS5cubls9DgAAILcU8fw+tizavXu3LV261CWEHzhwIOI+zfEUlIIljcQbO3asu63nqlGjht19993Wu3fvQM9x+umnW/v27e3xxx8/7LbKu6pQoYJt377dypcvb7mhZu8ZluhWD20f7yIAABBIVmKDbLU4zZw501JSUmzLli0Z7stKXtPevXstNTXV+vTpE1pXtGhRa9OmjS1YsOCwj1fM9/HHH7vWKSWlAwAA5LtRdWoNuuaaa2zDhg2uhSh8yUoyuAIvbV+tWrWI9bqtfKfMKCIsV66c66pTS5Nyotq2bRtz2z179kSM8mOkHwAAyK5stThpDiflJUUHPHnl6KOPdpNw/v777zZr1ixXlpNOOsnOO++8mFMnDBw4MC7lBAAAhUu2WpyuvvpqmzNnzhG/eFJSkhUrVizDZJq6nZycnOnj1J2niTYbN27sRtSpPAqQYlE3oFqo/EWXhgEAAMizFiclcqurbu7cudagQQMrUaJExP2aHDMIdbU1bdrUtRp17NjRrVN3n2737NkzcHn0GHXJxVKqVCm3AAAAxCVwevXVV+2DDz6w0qVLu5YnfxJM0d9BAydRN1vnzp2tWbNmbu4mTUewc+dON8WAKAm9evXqoRYl/a9tTz75ZBcsvffeezZp0iQbP358dt4KAABA7gZOmkdJeUOaLkDdZkeiU6dOtnnzZuvfv79LCFf3m0bt+flTa9eujXgNBVV33XWXu8xLmTJl3HxOkydPds8DAACQ7+Zx0iSUX3zxhWv1KWiYxylvMI8TAKAwxgbZai5S15pm/AYAAEgk2eqq09xLw4cPt/fff98aNmyYITl85MiROVU+AACAgh04LVu2zJo0aeL+/vrrr3O6TAAAAIUncJo9e3bOlwQAAKAwBU5XXnnlYbfRdARvvPHGkZQJAACg4AdOyjgHAABIVFkKnF588cXcKwkAAEA+d2SzVwIAACQQAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAoCAFTuPGjbOaNWta6dKlrUWLFrZw4cJMt33uuefsnHPOsUqVKrmlTZs2h9weAACg0AROU6dOtV69etmAAQNs8eLF1qhRI2vXrp1t2rQp5vZz5syx66+/3mbPnm0LFiywGjVq2EUXXWQ///xznpcdAAAkliKe53nxLIBamM444wwbO3asu33gwAEXDN19993Wu3fvwz5+//79ruVJj09JSTns9unp6VahQgXbvn27lS9f3nJDzd4zLNGtHto+3kUAACCQrMQGcW1x2rt3r6WmprrutlCBihZ1t9WaFMSuXbts3759Vrly5Zj379mzx1VI+AIAAJAdcQ2ctmzZ4lqMqlWrFrFetzdu3BjoOR5++GE77rjjIoKvcEOGDHFRpL+oNQsAAKBA5jgdiaFDh9qUKVNs+vTpLrE8lj59+rimN39Zt25dnpcTAAAUDsXj+eJJSUlWrFgxS0tLi1iv28nJyYd87FNPPeUCp48++sgaNmyY6XalSpVyCwAAQIFucSpZsqQ1bdrUZs2aFVqn5HDdbtmyZaaPGz58uD3++OM2c+ZMa9asWR6VFgAAJLq4tjiJpiLo3LmzC4CaN29uo0aNsp07d1qXLl3c/RopV716dZerJMOGDbP+/fvbK6+84uZ+8nOhypUr5xYAAIBCGzh16tTJNm/e7IIhBUGNGzd2LUl+wvjatWvdSDvf+PHj3Wi8q6++OuJ5NA/UY489luflBwAAiSPu8zjlNeZxyhvM4wQAKCgKzDxOAAAABQmBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABBQ8aAbAnmpZu8ZluhWD20f7yIAAKLQ4gQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEEJnMaNG2c1a9a00qVLW4sWLWzhwoWZbrt8+XK76qqr3PZFihSxUaNG5WlZAQBAYotr4DR16lTr1auXDRgwwBYvXmyNGjWydu3a2aZNm2Juv2vXLjvppJNs6NChlpycnOflBQAAiS2ugdPIkSOtW7du1qVLF6tbt65NmDDBypYtaxMnToy5/RlnnGEjRoyw6667zkqVKpXn5QUAAIktboHT3r17LTU11dq0aXOwMEWLutsLFizIsdfZs2ePpaenRywAAAAFKnDasmWL7d+/36pVqxaxXrc3btyYY68zZMgQq1ChQmipUaNGjj03AABILHFPDs9tffr0se3bt4eWdevWxbtIAACggCoerxdOSkqyYsWKWVpaWsR63c7JxG/lQpEPBQAACnTgVLJkSWvatKnNmjXLOnbs6NYdOHDA3e7Zs2e8igUUGjV7z4h3EfKF1UPbx7sIAAqRuAVOoqkIOnfubM2aNbPmzZu7eZl27tzpRtlJSkqKVa9e3eUp+Qnl33zzTejvn3/+2ZYsWWLlypWzWrVqxfOtAACABBDXwKlTp062efNm69+/v0sIb9y4sc2cOTOUML527Vo30s73yy+/WJMmTUK3n3rqKbe0bt3a5syZE5f3AAAAEkdcAydRt1xmXXPRwZBmDPc8L49KBgAAkGCj6gAAAHIKgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEVD7ohACSimr1nWKJbPbR9vIsA5BsETgCAXEXwSfBZmNBVBwAAEBCBEwAAQEHqqhs3bpyNGDHCNm7caI0aNbIxY8ZY8+bNM93+9ddft0cffdRWr15tp5xyig0bNswuueSSPC0zAAB5he5OyzfdnXFvcZo6dar16tXLBgwYYIsXL3aBU7t27WzTpk0xt58/f75df/31dtttt9mXX35pHTt2dMvXX3+d52UHAACJJe6B08iRI61bt27WpUsXq1u3rk2YMMHKli1rEydOjLn96NGj7eKLL7aHHnrI6tSpY48//ridfvrpNnbs2DwvOwAASCxxDZz27t1rqamp1qZNm4MFKlrU3V6wYEHMx2h9+PaiFqrMtgcAACgUOU5btmyx/fv3W7Vq1SLW6/aKFStiPkZ5ULG21/pY9uzZ4xbf9u3b3f/p6emWWw7s2WWJ7kjrlzqkDnMK9XjkqMMjRx0eudw8bvvP7XlewUgOz01DhgyxgQMHZlhfo0aNuJQnUVQYFe8SFHzUYc6gHo8cdXjkqMOCUYc7duywChUq5N/AKSkpyYoVK2ZpaWkR63U7OTk55mO0Pivb9+nTxyWf+w4cOGBbt261KlWqWJEiRaywUdSsoHDdunVWvnz5eBenwKIejxx1eOSow5xBPR65wl6Hnue5oOm444477LZxDZxKlixpTZs2tVmzZrmRcX5go9s9e/aM+ZiWLVu6+++7777Qug8//NCtj6VUqVJuCVexYkUr7LRjF8adO69Rj0eOOjxy1GHOoB6PXPlCXIeHa2nKN111ag3q3LmzNWvWzM3dNGrUKNu5c6cbZScpKSlWvXp11+Um9957r7Vu3dr+/ve/W/v27W3KlCm2aNEie/bZZ+P8TgAAQGEX98CpU6dOtnnzZuvfv79L8G7cuLHNnDkzlAC+du1aN9LOd9ZZZ9krr7xi/fr1s0ceecRNgPnWW29Z/fr14/guAABAIoh74CTqlsusa27OnDkZ1l1zzTVuQUbqltRkotHdk8ga6vHIUYdHjjrMGdTjkaMODyriBRl7BwAAgPjPHA4AAFBQEDgBAAAEROAEAAAQEIETAABAQAROBZQmCgUAAHmLwKmAefnll93U8OFzWyF7GFCadQTsOYv6BAoejr4FyFNPPWV33nmnffXVV/EuSoH22Wefuf8L47UKc5sfsP/3v/+Nd1EKpE8++ST096BBg2z06NFxLQ8SV6ygnZPJYAicCogFCxbY6tWrbfr06W52dWSPLtHTvXv3eBejQPv555/d5Y7GjRsX76IUKJs2bbKrrrrK2rVr5661OXz4cPc3sufNN990l976+OOPbfv27fEuToELmvyToB9//NG+++479zcnk8EQOBUA7777rt1xxx02Y8YMO/744906mvizR5fy+eWXXywtLY2zq4D2798fcdu/duSrr75qqampcStXQVO1alWbO3euOwnStTXnz59vdevWtT///DPeRStw+vTpY7fccotNnjzZBZ+PPvqoLVu2LN7FKjD8oEn1eP7559u5555rF110ka1ZsybeRSsQCJwKgL/85S9Wr149dy2/9957L7TjEzxlXc2aNd1ZVXp6uvs/OihARsWKFXP/T5s2zV2AWzp06GAlSpSwDz74wN1mX8xceN0oaNJ+d/TRR7trbSp4L168eIb6I6jPnIL1xYsX2/vvv29ffvmlC54+/PBDe/rpp23p0qXxLl6+Fv5799prr7kWeLXajR8/3p1MXnrppdRhQblWHQ6tUaNG7hpBOoDpLD8pKcm6dOkSCp5IFD80/aB+8cUX7gLRxx57rGt10gFMF4j2g4LwAxbN1RnpIHXttdfaBRdc4K4TqYtz33XXXe6sX0GUWk7YFzMKH8jx8MMP2/Lly12rk+pKB6m//vWv7qLm4fWmg1v0fon/owP8vHnzrFKlSnbGGWe4ddoX5bHHHnPf3bvvvtsaNGgQ55LmL3v27HHXmPP3qzfeeMN+/fVXt09effXVbl3btm2tdevWdsMNN7jjDHWYOX7l8ikd6HWwUvS/e/duq127tv3tb39zLU/PP/+8vfTSS247/eBydpq5rVu3uj78LVu2uB+De++9177//nvr3bu3XXjhhdavXz83UlFnXkLQ9H+iW0BOO+00O/HEE11T/vr16+2yyy6zk08+2f3oKmfs999/J2iKwd+fvvnmG3fAV9dIw4YNXZ7i1KlT7euvv3b5Yn53nbrk9f1GbDt27HAtn2pxUs6nT8HTwIEDXfenku5/+OGHuJYzP1EwFD6Y47fffrPbbrvNevTo4dIWRMeQcuXK2aeffmqlS5e2m266ydUxMqGL/CJ/6d27t3faaad5SUlJ3rnnnut17drV27Fjh7tvyZIl3s033+ydc8453rhx4+Jd1ALn+++/9/761796l1xyiffoo4961157rVejRg2vffv23v79++NdvHxn+fLl3q+//ur+/u9//+vVr1/fe/nll72nn37aq1SpkqvLatWqec888wz1l4nBgwd7l156qXfllVd6O3fujLhv3rx5bv+rVauWd+aZZ3onn3yyt2/fvriVtSB47rnnvGOOOcb729/+5q1Zsybivpdeesm74YYb2BfDPPXUU97u3bvd3/6+9d1333mNGjXymjVr5q1fv96tO3DggPv/999/944//njvpptuimOp8zcCp3xmyJAhXnJysvfJJ5+4HblHjx5e2bJl3Y/u9u3b3TZfffWVO9DfcccdoZ0dkX755Rdv69at7kdAwg9GqmP9YPgUlPr1SH0e9M4773i1a9f2Onfu7AJO6dOnjzdgwAD398cff+zuK1KkiNelS5c4lzb/iD5oK9BUHSnA/OabbzJsrwPXgw8+6OrV30///PPPPCtvfqfA3T+4+/7xj3941atX9x555BFv7dq1MR+X6MFT9Pt/8sknvbFjx4Z+ExU8nXDCCd7555/vbdy4MeL3748//mAfPAQCp3xkxYoV3tlnn+29++677vb777/vHXXUUV5KSopXp04d1zritzzpQOZ/MTjYZzzDb968udewYUPvvPPO81avXu3W79271/3/yiuvuDN7/7Yv0X9oY+1Hzz77rHfFFVd45cuX91599VVv1KhR7od22bJl7v4NGzZ4c+bM4Uc2Bp3g6ADkB6EKnu666y5v06ZNh6xzWpwOGjhwoNeqVSuvQoUK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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Model-based \n", + "plt.figure(figsize=(6,4))\n", + "plt.bar(range(len(feat_order)), imp_model_sorted)\n", + "plt.xticks(range(len(feat_order)), feat_order, rotation=45, ha=\"right\")\n", + "plt.ylabel(\"Importance\")\n", + "plt.title(\"Feature Importance (Model-based)\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4cc5e5d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAGGCAYAAACNCg6xAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAARGpJREFUeJzt3QncVOP///FP+yLtq0Qh0k5ZWhRZQiRbWSsqIZQSJbSQElKSQuirSETiK5H2FClFRb6WVGjVvlPn/3hfv/8ZM3Pfd52pe+77nntez8fj1MyZc89cc811zvmcazs5PM/zDAAAAIeV8/CbAAAAQAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAJJ01a9ZY/vz57YsvvsjspCSs0aNHW44cOey3337L7KRkW99//73lzp3bli1bltlJQRgCJ8TlYJra0qNHj7h85rx586xPnz62detWy6r5sXDhQktUL774ovse2Um/fv3snHPOsQYNGoTWtW3bNqK8Fi5c2GrVqmXPPvus7du3zxLR5MmT3b5xNJ588kn74IMPLJlEl4W0Fm2XHt566y0bMmRIivVVq1a1Zs2a2WOPPZYun4P0kTud3gdIcWKqVKlSxLrq1avHLXDq27evO4gVLVo0Lp+RzBQ4lSxZMt1OEplt48aN9p///Mct0fLly2ejRo1yjxWIv/fee/bAAw/Y119/bW+//bYlYuA0fPjwowqeFDhdd9111qJFi4j1t956q91www0uz7Kbjh072kUXXRR6vnLlShe83HHHHXbeeeeF1p988snpFjipVqlLly4pXrvzzjvt8ssvt19++SXdPg9Hh8AJcXHZZZdZ3bp1LZHt2rXLjjnmGEtWu3fvtoIFC1p2M3bsWNf8ceWVV6Z4TetvueWW0PO7777b1UyNHz/eBg8ebMcdd9wRf+7Bgwdt//79rokwO8iVK5dbsqN69eq5xacaYwVOWhdePjKCArhixYq5QF8XpMh8NNUhU3zyySfuyk2BybHHHuuqo5cvXx6xzXfffedqOU466SR3silbtqzdfvvt9tdff4W20ZV09+7d3WPVcPlV6Op3oUWPU2tm0vrwq3A91jr1Kbjpppvcgaphw4YRJ9s6depYgQIFrHjx4u5KW/1kjoS+U6FChWz16tV2xRVXuMfly5d3NQOydOlSa9KkicubE0880V2Nptb8N3v2bHdlXKJECdes1Lp1a9uyZUuqNUbVqlVzNQM68Xfq1ClFs+b555/vagQXLVpkjRo1cgHTww8/bBUrVnS/y6xZs0J5q21l8+bNrjamRo0a7jsoDQqYv/3224j3njlzpvu7d955x/r372/HH3+8+z0vvPBC+/nnn1Ok96uvvnJX2PoNlAc1a9a0oUOHRmyzYsUKVwui30LvpSD9ww8/DJT/anZSMKQ0H07OnDlD39fvy6Nmu969e9spp5zi8rRChQr24IMPpmjO03e+55577M033wzl/5QpU0K/39y5c+2+++6zUqVKuZpS/ZYKrPTb6LfU99ei9/Y8L0V+6v9w0eVd5cwvU+HNS75nnnnG6tev78qPyrXK94QJE1J8B11A6KQd3TyVVh+nWMqb9rcLLrjAlTftA4MGDbIg/vnnH3v88cddDYw+R+VU5TX6N9B67WPK67PPPtuVFR1P3njjDUsPKquXXnqpFSlSxH2Hxo0bp+g3t2PHDleTpLQoraVLl7aLL77Yvvnmm1BefPzxx7Zq1apQHmtbX548edw2kyZNSpc04+hR44S42LZtm23atClinZp7ZMyYMdamTRtr2rSpPfXUU65mY8SIES5QWbx4ceigMXXqVPv111/ttttuc0GTTuAvv/yy+//LL790B5hrrrnG/ve//9m4cePsueeeC32GTkZqkonV9ddfb5UrV3bNE/7JSif7Rx991Fq2bGnt27d37zts2DAXYCi9R9I8eODAARdk6D10stDJVSdZBQq9evWym2++2X23kSNHupOornSjmz61vT5bQd+PP/7o8lAHX//EKnpNzZi6ar3rrrtC26npSQd4HZR9CkiVJgWFuqouU6aMO2Dfe++9LshQukTrRb+NghDlmdK2fv16e+mll9zJQyfE6NqZgQMHukBEwZbKh763vqdOPj795jrRlStXzjp37ux+9x9++MH++9//uuei3199k3SiVb855ZmCMjUlqWnt6quvTjPf//77b/fdlRdBqYlEFGCo1qh58+buRKxmm9NPP90Fuip7KofRfYGmT5/u0qbfSmVTZXvJkiXuNeWrvp9+H5VnlW39nmp6PuGEE1wZVFPb008/7YIMlYNYKBD7888/XZ5qn4umYFTfRb+BAjY1Req3VF7rQkb0dyrzCjr0feVQ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lmVo2gEAQPLJ4XmeZ1nExo0bXc2TAqpGjRqluk2rVq1cYPXf//43tO7cc8+12rVr28iRIw/7Gdu3b7ciRYrYtm3brHDhwhYPFXt8bMnut4HNMjsJAAAEEktskKX6OCnBUrx42nMTzZ8/3y666KKIdU2bNnXrU7Nv3z6XIeELAADAkcgygdPBgwetS5cu1qBBA6tevXqa261bt87KlCkTsU7PtT6tflSKIv2lQoUK6Z52AACQHLJM4KS+Tuqn9Pbbb6fr+/bs2dPVZPnLmjVr0vX9AQBA8sgSt1y55557XJ+l2bNn2/HHH3/IbcuWLWvr16+PWKfnWp+afPnyuQUAACCha5zUL11B08SJE2369OlWqVKlw/5NvXr1bNq0aRHrNCJP6wEAALJtjZOa59566y2bNGmSm8vJ76ekvkgFChRwj1u3bm3ly5d3fZWkc+fO1rhxY3v22WetWbNmrmlv4cKF9vLLL2fmVwEAAEkgU2ucRowY4fodnX/++VauXLnQMn78+NA2q1evtrVr14ae169f3wVbCpRq1aplEyZMsA8++OCQHcoBAAASvsYpyBRSM2fOTLHu+uuvdwsAAEBSjqoDAADI6gicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAADIiMBp37596ZcSAACA7BQ4ffLJJ9amTRs76aSTLE+ePFawYEErXLiwNW7c2Pr3729//vln/FIKAACQCIHTxIkT7dRTT7Xbb7/dcufObQ899JC9//779umnn9qoUaNc4PT555+7gOrOO++0jRs3xj/lAAAAGSx3kI0GDRpkzz33nF122WWWM2fKWKtly5bu/z/++MOGDRtmY8eOtfvvvz/9UwsAAJDVA6f58+cHerPy5cvbwIEDjzZNAAAAWRKj6gAAANKzxincgQMHbPTo0TZt2jTbsGGDHTx4MOL16dOnx/qWAAAA2TNw6ty5swucmjVrZtWrV7ccOXLEJ2UAAACJHji9/fbb9s4779jll18enxQBAABklz5OefPmtVNOOSU+qQEAAMhOgVO3bt1s6NCh5nlefFIEAACQXZrq5s6dazNmzHCziFerVs3NIB5OE2MCAABkRzEHTkWLFrWrr746PqkBAADIToHT66+/Hp+UAAAAZHFMgAkAABCvGieZMGGCm5Jg9erVtn///ojXvvnmmyN5SwAAgOxX4/T888/bbbfdZmXKlLHFixfb2WefbSVKlLBff/3V3QQYAAAgu4o5cHrxxRft5ZdftmHDhrk5nR588EGbOnWq3XfffbZt27aY3mv27Nl25ZVX2nHHHedmIP/ggw8Ouf3MmTPddtHLunXrYv0aAAAA8Q+c1DxXv35997hAgQK2Y8cO9/jWW2+1cePGxfReu3btslq1atnw4cNj+rsff/zR1q5dG1pKly4d098DAABkSB+nsmXL2ubNm+3EE0+0E044wb788ksX/KxcuTLmSTHVtHckzXsKlDQtAgAAQJaucWrSpIl9+OGH7rH6Ot1///128cUXW6tWrTJsfqfatWtbuXLl3Od+8cUXh9x23759tn379ogFAAAgQ2qc1L/p4MGD7nGnTp1cx/B58+ZZ8+bNrWPHjhZPCpZGjhxpdevWdQHRqFGj7Pzzz7evvvrKzjzzzFT/ZsCAAda3b9+4pgsAACSHHF4WuemcOnlPnDjRWrRoEdPfNW7c2DUZjhkzJtXXFWBp8anGqUKFCq4je+HChS0eKvb42JLdbwObZXYSAAAIRLFBkSJFAsUGRzQB5pw5c+yWW26xevXq2R9//OHWKXDRfewymqZD+Pnnn9N8PV++fC4TwhcAAIAjEXPg9N5771nTpk3diDrN4+TX5ihKe/LJJy2jLVmyxDXhAQAAZLnA6YknnnD9jF555RXLkydPaH2DBg1injV8586dLvDRIhqZp8ea8kB69uxprVu3Dm0/ZMgQmzRpkqthWrZsmXXp0sWmT5/u+loBAABkuc7hmkOpUaNGKdarbXDr1q0xvdfChQvtggsuCD3v2rWr+79NmzY2evRoN0eTH0SJbu/SrVs31zxYsGBBq1mzpn3++ecR7wEAAJCl5nFSjU/FihUj1qt/00knnRTTe2lE3KH6pit4CqdZyrUAAAAkRFNdhw4drHPnzm4KAI2E+/PPP+3NN9+0Bx54wO666674pBIAACARa5x69Ojh5nG68MILbffu3a7ZTiPXFDjde++98UklAABAIgZOqmXq1auXde/e3TXZqYN31apVrVChQvFJIQAAQKIGTr68efO6gAkAACBZxBw47d2714YNG2YzZsywDRs2hG6/4ot1SgIAAIBsGzi1a9fOPvvsM7vuuuvcrN1qugMAAEgGMQdO//3vf23y5MluwksAAIBkEvN0BOXLl7djjz02PqkBAADIToHTs88+aw899JCtWrUqPikCAADILk11devWdR3ENUu4bnsSfr862bx5c3qmDwAAIHEDpxtvvNHdK+7JJ5+0MmXK0DkcAAAkjZgDp3nz5tn8+fOtVq1a8UkRAABAdunjVKVKFduzZ098UgMAAJCdAqeBAwdat27dbObMmfbXX3/Z9u3bIxYAAIDsKuamuksvvdT9r5v8hvM8z/V3OnDgQPqlDgAAIJEDJ91qBQAAIBnFHDg1btw4PikBAADIDn2cVq9eHdObaroCAACApAyczjrrLOvYsaN9/fXXaW6zbds2e+WVV6x69er23nvvpWcaAQAAEqep7vvvv7f+/fvbxRdfbPnz57c6derYcccd5x5v2bLFvb58+XI788wzbdCgQXb55ZfHP+UAAABZscapRIkSNnjwYFu7dq298MILVrlyZdu0aZP99NNP7vWbb77ZFi1a5CbGJGgCAADZVUydwwsUKGDXXXedWwAAAJJNzBNgAgAAJCsCJwAAgIAInAAAAAIicAIAAAiIwAkAACCegdOYMWOsQYMGbi6nVatWuXVDhgyxSZMmHcnbAQAAZM/AacSIEda1a1c3X9PWrVvtwIEDbn3RokVd8AQAAJBdxRw4DRs2zN1apVevXpYrV67Q+rp169rSpUvTO30AAACJGzitXLnSzjjjjBTr8+XLZ7t27UqvdAEAACR+4FSpUiVbsmRJivVTpkyx008/Pb3SBQAAkNi3XBH1b+rUqZPt3bvXPM+zBQsW2Lhx42zAgAE2atSo+KQSAAAgEQOn9u3bu3vWPfLII7Z792676aab3Oi6oUOH2g033BCfVAIAACRi4CQ333yzWxQ47dy500qXLp3+KQMAAEj0wEmdw//55x+rXLmyFSxY0C3y008/WZ48eaxixYrxSCcAAEDidQ5v27atzZs3L8X6r776yr0GAACQXcUcOC1evNjNGh7t3HPPTXW0HQAAQNIGTjly5LAdO3akWL9t27bQLOIAAADZUcyBU6NGjdzUA+FBkh5rXcOGDdM7fQAAAInbOfypp55ywdNpp51m5513nls3Z84c2759u02fPj0eaQQAAEjMGqeqVavad999Zy1btrQNGza4ZrvWrVvbihUrrHr16vFJJQAAQKLO46QJL5988sn0Tw0AAEB2C5y2bt3qbrWiGqeDBw9GvKbaJwAAgOwo5sDpo48+crOGa8bwwoULu1F2Pj0mcAIAANlVzH2cunXrZrfffrsLnFTztGXLltCyefPm+KQSAAAgEQOnP/74w+67777QrVYAAACSRcyBU9OmTW3hwoXxSQ0AAEB26uPUrFkz6969u33//fdWo0YNd2PfcM2bN0/P9AEAACRu4NShQwf3f79+/VK8ps7h3HYFAABkVzEHTtHTDwAAACSLmPs4AQAAJKsjmgBz165dNmvWLFu9erXt378/4jWNuAtq9uzZ9vTTT9uiRYts7dq1NnHiRGvRosUh/2bmzJnWtWtXW758uVWoUMEeeeQRa9u27ZF8DQAAgPgGTosXL7bLL7/cdu/e7QKo4sWL26ZNm9z0BKVLl44pcNLf16pVy80Ldc011xx2+5UrV7rO6Xfeeae9+eabNm3aNGvfvr2VK1fOjfYDAADIUoHT/fffb1deeaWNHDnSihQpYl9++aUbWXfLLbdY586dY3qvyy67zC1B6TMrVapkzz77rHt++umn29y5c+25554jcAIAAFmvj9OSJUvc7OE5c+a0XLly2b59+1yT2aBBg+zhhx+2eJo/f75ddNFFEesUMGl9WpS+7du3RywAAAAZEjipdklBk6hpTv2cRLVPa9assXhat26dlSlTJmKdnisY2rNnT6p/M2DAAJc2f1GQBwAAkCGB0xlnnGFff/21e9y4cWN77LHHXH+jLl26WPXq1S2r6dmzp23bti20xDu4AwAA2VfMgdOTTz7pOmNL//79rVixYnbXXXfZxo0b7aWXXrJ4Klu2rK1fvz5inZ4XLlzYChQokOrf5MuXz70evgAAAGRI5/C6deuGHqupbsqUKZZR6tWrZ5MnT45YN3XqVLceAAAgy9U4NWnSxLZu3ZpivfoZ6bVY7Ny503U21+JPN6DHfr8pNbO1bt06tL2mIfj111/twQcftBUrVtiLL75o77zzjhvpBwAAkOUCJ01AGT3ppezdu9fmzJkT03stXLjQ9ZnSIprYUo/Vb0o0KaYfRImmIvj4449dLZPmf9K0BKNGjWIqAgAAkLWa6r777rvQ4++//96NcPPpxr5qsitfvnxMH37++eeb53lpvj569OhU/0aTcAIAAGTZwKl27dqWI0cOt6TWJKfO2cOGDUvv9AEAACRe4KT+R6odOumkk2zBggVWqlSp0Gt58+Z1HcU1ISYAAIAle+B04okn2t9//21t2rSxEiVKuOcAAADJJGess4ZPnDgxfqkBAADITqPqrrrqKvvggw/ikxoAAIDsNAFm5cqVrV+/fvbFF19YnTp17Jhjjol4/b777kvP9AEAACRu4PTqq69a0aJFbdGiRW4JpxF3BE4AACC7ijlw0ug6AACAZBRzH6dwmp7gUBNYAgAAWLIHTm+88YbVqFHDTXqppWbNmjZmzJj0Tx0AAEAiN9UNHjzYHn30UbvnnnusQYMGbt3cuXPdDXg3bdrEDXcBAEC2FXPgpNuqjBgxwlq3bh1a17x5c6tWrZr16dOHwAkAAGRbMTfVrV271urXr59ivdbpNQAAgOwq5sDplFNOsXfeeSfF+vHjx7s5ngAAALKrmJvq+vbta61atbLZs2eH+jhpMsxp06alGlABAAAkbY3Ttddea1999ZWVLFnS3XpFix4vWLDArr766vikEgAAIBFrnES3Whk7dmz6pwYAACC7BU4HDhywiRMn2g8//OCeV61a1d38N3fuI3o7AACAhBBzpLN8+XI3/cC6devstNNOc+ueeuopK1WqlH300UdWvXr1eKQTAAAg8fo4tW/f3s3Z9Pvvv9s333zjljVr1rjZw++44474pBIAACALiLnGacmSJbZw4UIrVqxYaJ0e9+/f384666z0Th8AAEDi1jideuqptn79+hTrN2zY4OZ4AgAAyK5iDpwGDBhg9913n02YMME112nR4y5duri+Ttu3bw8tAAAASd1Ud8UVV7j/W7ZsaTly5HCPPc9z/1955ZWh53pNo+8AAACSNnCaMWNGfFICAACQ3QKnxo0bxyclAAAAWdwRzVi5d+9e++6771yH8IMHD0a8pjmeAAAAsqOYA6cpU6ZY69atbdOmTSleo18TAADIzmIeVXfvvffa9ddfb2vXrnW1TeELQRMAAMjOYg6cNIdT165drUyZMvFJEQAAQHYJnK677jqbOXNmfFIDAACQnfo4vfDCC66pbs6cOVajRg3LkydPxOuaHBMAACA7ijlwGjdunH322WeWP39+V/PkT4IpekzgBAAAsquYA6devXpZ3759rUePHpYzZ8wtfQAAAAkr5shn//791qpVK4ImAACQdGKOftq0aWPjx4+PT2oAAACyU1Od5moaNGiQffrpp1azZs0UncMHDx6cnukDAABI3MBp6dKldsYZZ7jHy5Yti3gtvKM4AACAJXvgNGPGjPikBAAAIIujhzcAAEB61zhdc801gbZ7//33g74lAABA9gycihQpEt+UAAAAZJfA6fXXX49vSgAAALI4+jgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAACRS4DR8+HCrWLGi5c+f38455xxbsGBBmtuOHj3acuTIEbHo7wAAALJ94DR+/Hjr2rWr9e7d27755hurVauWNW3a1DZs2JDm3xQuXNjWrl0bWlatWpWhaQYAAMkp0wOnwYMHW4cOHey2226zqlWr2siRI61gwYL22muvpfk3qmUqW7ZsaClTpkyGphkAACSnTA2c9u/fb4sWLbKLLrro3wTlzOmez58/P82/27lzp5144olWoUIFu+qqq2z58uUZlGIAAJDMMjVw2rRpkx04cCBFjZGer1u3LtW/Oe2001xt1KRJk2zs2LF28OBBq1+/vv3++++pbr9v3z7bvn17xAIAAJCQTXWxqlevnrVu3dpq165tjRs3tvfff99KlSplL730UqrbDxgwwIoUKRJaVEsFAACQcIFTyZIlLVeuXLZ+/fqI9XquvktB5MmTx8444wz7+eefU329Z8+etm3bttCyZs2adEk7AABIPpkaOOXNm9fq1Klj06ZNC61T05ueq2YpCDX1LV261MqVK5fq6/ny5XOj8MIXAACAI5HbMpmmImjTpo3VrVvXzj77bBsyZIjt2rXLjbITNcuVL1/eNblJv3797Nxzz7VTTjnFtm7dak8//bSbjqB9+/aZ/E0AAEB2l+mBU6tWrWzjxo322GOPuQ7h6rs0ZcqUUIfx1atXu5F2vi1btrjpC7RtsWLFXI3VvHnz3FQGAAAA8ZTD8zzPkohG1amTuPo7xavZrmKPjy3Z/TawWWYnAQCAdI8NEm5UHQAAQGYhcAIAAAiIwAkAACAgAicAAICACJwAAAACInACAABIlHmcgMy2du1atwSlWerTmqkeAJC9ETgh6ekG0X379g28fe/eva1Pnz5xTRMAIGsicEKWlJGTiO5bX8JKXNEt9Nz752/bPOV597j4pfdZjtx5IrZ/aVUJG50B6WMSUQDIegickPT2/DTftn0xLtXX/AAqXJEGN1q+MidlQMoAAFkNgROSXqHal1mBU84JvH2uQsXjmh4AQNZF4ISkl7tQcbcAAHA4TEcAAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAASUO+iGAJCWtWvXuiWocuXKuQUAEg2BE4Cj9swzz9jgwYMDb9+1a1d79tln45omAIgHAicgm6rY4+MM+6zNc36NaftX5vxq72VQ+n4b2CxDPgdAciBwAnDUCp99jR1T9fzA2+cqVDyu6QGAeCFwAnDUchcq7hYAyO4YVQcAABAQgRMAAEBABE4AAACJFDgNHz7cKlasaPnz57dzzjnHFixYcMjt3333XatSpYrbvkaNGjZ58uQMSysAAEhemR44jR8/3s3p0rt3b/vmm2+sVq1a1rRpU9uwYUOq28+bN89uvPFGa9eunS1evNhatGjhlmXLlmV42gEAQHLJ9FF1mjSvQ4cOdtttt7nnI0eOtI8//thee+0169GjR4rthw4dapdeeql1797dPX/88cdt6tSp9sILL7i/BYBEtGTJElu+fHng7atVq2a1a9eOa5oSEfmIbB047d+/3xYtWmQ9e/YMrcuZM6dddNFFNn/+/FT/RutVQxVONVQffPBB3NMLIPlk1ESi697qYfvWBK85z1ehupW9aaAlwiSiGTkZa1bNx0SaiJXgMwsHTps2bbIDBw5YmTJlItbr+YoVK1L9m3Xr1qW6vdanZt++fW7xbdu2zf2/fft2i5eD+3Zbsjva/CUPycNky8eijVrb33+tCbx9nhIVMixtiZKHWTkfjzYPq/f+1DLK+nd72/4/fgi8fd7yp1uZ6/tavC3r2zTuv4/neVm/qS7eBgwYYH37pvxBK1SokCnpSRZFhmR2ChIfeZg+yMejRx4eveych/v/+MHWDGmZLfJwx44dVqRIkawbOJUsWdJy5cpl69evj1iv52XLlk31b7Q+lu3VDBjetHfw4EHbvHmzlShRwnLkyGHZjaJmBYVr1qyxwoULZ3ZyEhb5ePTIw6NHHqYP8vHoZfc89DzPBU3HHXfcYbfN1MApb968VqdOHZs2bZobGecHNnp+zz33pPo39erVc6936dIltE6dw7U+Nfny5XNLuKJFi1p2p4KdHQt3RiMfjx55ePTIw/RBPh69wtk4Dw9X05RlmupUG9SmTRurW7eunX322TZkyBDbtWtXaJRd69atrXz58q7JTTp37myNGze2Z5991po1a2Zvv/22LVy40F5++eVM/iYAACC7y/TAqVWrVrZx40Z77LHHXAdv9cyfMmVKqAP46tWr3Ug7X/369e2tt96yRx55xB5++GGrXLmyG1FXvXr1TPwWAAAgGWR64CRqlkuraW7mzJkp1l1//fVuQUpqltRkotHNk4gN+Xj0yMOjRx6mD/Lx6JGH/8rhBRl7BwAAgMy/5QoAAECiIHACAAAIiMAJAAAgIAInAACAgAicEpQmCgUAABmLwCnBvPHGG25q+PC5rXBkGFAaOwL29EV+AomHs28CeeaZZ+zOO++0b7/9NrOTktC++OIL9392vFdhvPkB+yeffJLZSUlIs2bNCj3u16+fDR06NFPTg+SVWtDOxWQwBE4JYv78+fbbb7/ZxIkT3ezqODK6Rc9dd92V2clIaH/88Ye73dHw4cMzOykJZcOGDXbttdda06ZN3b02Bw0a5B7jyLz//vvu1lvTp0+3bdu2ZXZyEi5o8i+Cfv31V/vf//7nHnMxGQyBUwL46KOPrGPHjvbxxx/b8ccf79ZRxX9kdCufP//809avX8/VVUAHDhyIeO7fO3LcuHG2aNGiTEtXoildurTNmTPHXQTp3prz5s2zqlWr2j///JPZSUs4PXv2tLZt29rYsWNd8Pnoo4/a0qVLMztZCcMPmpSPF1xwgTVq1MguueQSW7VqVWYnLSEQOCWAE044wapVq+bu5Td58uRQwSd4il3FihXdVdX27dvd/9FBAVLKlSuX+3/ChAnuBtxy1VVXWZ48eeyzzz5zzymLaQvPGwVNKnfHHnusu9emgvfcuXOnyD+C+rQpWP/mm2/s008/tcWLF7vgaerUqfb888/bd999l9nJy9LCj3fvvPOOq4FXrd2IESPcxeQVV1xBHibKvepwaLVq1XL3CNIJTFf5JUuWtNtuuy0UPNFR/NB0QP3666/dDaLLlSvnap10AtMNov2gIPyERXV1SjpJtWzZ0po0aeLuE6mbc999993uql9BlGpOKIsphQ/keOihh2z58uWu1kl5pZPUZZdd5m5qHp5vOrlFl0v8H53g586da8WKFbOzzjrLrVNZlD59+rh9995777UaNWpkckqzln379rl7zPnl6r333rO//vrLlcnrrrvOrbv44outcePGdtNNN7nzDHmYNo5yWZRO9DpZKfrfu3evValSxR588EFX8zRq1CgbPXq0204HXK5O07Z582bXhr9p0yZ3MOjcubP99NNP1qNHD7vwwgvtkUcecSMVdeUlBE3/J7oG5LTTTrNKlSq5qvzff//drrzySjv55JPdQVd9xnbu3EnQlAq/PH3//ffuhK+mkZo1a7p+iuPHj7dly5a5/mJ+c52a5LV/I3U7duxwNZ+qcVKfT5+Cp759+7rmT3W6/+WXXzI1nVmJgqHwwRxbtmyxdu3aWadOnVy3BdE5pFChQjZ79mzLnz+/3XLLLS6PkQbd5BdZS48ePbzTTjvNK1mypNeoUSOvffv23o4dO9xrS5Ys8W699VbvvPPO84YPH57ZSU04P/30k3fZZZd5l19+uffoo496LVu29CpUqOA1a9bMO3DgQGYnL8tZvny599dff7nHn3zyiVe9enXvjTfe8J5//nmvWLFiLi/LlCnjvfTSS+RfGp588knviiuu8K655hpv165dEa/NnTvXlb9TTjnFO/fcc72TTz7Z+/vvvzMtrYnglVde8UqVKuU9+OCD3qpVqyJeGz16tHfTTTdRFsM888wz3t69e91jv2z973//82rVquXVrVvX+/333926gwcPuv937tzpHX/88d4tt9ySianO2gicspgBAwZ4ZcuW9WbNmuUKcqdOnbyCBQu6g+62bdvcNt9++6070Xfs2DFU2BHpzz//9DZv3uwOAhJ+MlIe64DhU1Dq5yP5+a8PP/zQq1KlitemTRsXcErPnj293r17u8fTp093r+XIkcO77bbbMjm1WUf0SVuBpvJIAeb333+fYnuduB544AGXr345/eeffzIsvVmdAnf/5O577rnnvPLly3sPP/ywt3r16lT/LtmDp+jv379/f++FF14IHRMVPJ144oneBRdc4K1bty7i+Ldnzx7K4CEQOGUhK1as8Bo2bOh99NFH7vmnn37qHXPMMV7r1q29008/3dWO+DVPOpH5OwYn+5RX+GeffbZXs2ZN7/zzz/d+++03t37//v3u/7feestd2fvPfcl+oE2tHL388sve1Vdf7RUuXNgbN26cN2TIEHegXbp0qXt97dq13syZMznIpkIXODoB+UGogqe7777b27BhwyHznBqnf/Xt29dr0KCBV6RIEa9Dhw7e5MmTQ68NHjzY1Yw88sgj3q+//pqp6UwEd9xxhyuDr732WorgqUmTJimCJ2G/Th2BUxbz5ptvutqSL774witXrpxrAhE1z+XMmdM13fmFXpL9ZB+tV69eXunSpb2xY8d6U6ZM8erUqeOdcMIJoRO9f7JXM+jChQszNa1ZSXg5Wrlypbdo0SJv9+7dESewSpUqeffcc49XvHhx78ILL/T27dsX8R4cZP81YcIE79RTT/VGjRoVaiZ5++233YmrW7du3saNG0Pbsg+nTk3pqqVTjd3s2bO9qlWrugshXfj4FMjnypUrdJzEocuUyl6ePHm8V199NSJ4Oumkk7waNWq4WnocHoFTFqD+Ivfff3/EOlXd33777aGT0xNPPOFdfPHFruBzoE2dmo4UKM2ZMyd0la8rVZ3ASpQoEQqe1G/nqquuIh//v/ArTAWeasY89thjXf+le++9N/T6Z5995sqp+t8pAFCQj9Rt377du/LKK7369eu7K3w/eFKtnfKue/fu3vr16zM7mVl6X65WrZoLmGTevHle3rx5XfB0zjnneO+++25oWwWkBO3/Cj+uqU/sd999F3ER1KVLlxTBk5qQ1R2EfAyGwCmTKTBSZ/CmTZt6W7duDa2/+eabXRW179prr3Xt0z5O+il9+eWXXr9+/dxj1TapA6k60P/yyy+u1kk1JtG1TBwoIps4VRP3+eefe5s2bfJuvPFGF3jOnz8/tI2amXQya9WqFXl3mH1RJ6UWLVq4E3148DR+/HgXPA0bNiyDU5o4fvzxx9DgF3VZUC2nOn7/8ccfroxqcIyakcNRHiMpOFcznAJO7ct+FxA/eMqXL58rl373Dx/5eHgETlnAggULXF8mvwpaB+LXX3/d1Z7o6l8HXvVx8vs+0KcpbWqnV/6ptuShhx5y63TCUm2d+unofyEP/6W8UAfcSy65xNWIhPev0wgmCb9iDUd/nH+pSUm1nOF0UlLwpJoSve4HTwpOybu0qbypTOp/jYDt06dPKEBt3Lix68ag2nf8K/yYpn6HKnMzZszwPvjgA1fzqf1btXO+rl27ugA+PKBCMEyAmQVoIjfdu2rIkCF23nnnuduqaJJBzYuzcOFCN0PzU0895WYYZnK8SLrhsfLp1FNPdRO8+bdUWbFihd1+++2hyd+KFi3qZrn2J81L9vmawierVF5oDhfd70vzhekWP5oETzeVbt++ve3fv9/eeustN5dTw4YNI95HZTJZheeh8ki3odHEjCqHun2FKF8179Dpp59uw4YNc3l8xx13uDnERPM3JXMehtMs4JqnSZPUaob/4sWL2+7du23t2rVWsGBBl9fal/Wa5rS79NJLMzvJWUb05LMqd7oVzfnnn++ea7Lf+++/31599VW3v2syW80YfuKJJ5KPRyJggIV0pP5KGk77zTffRLTp6wph6tSpaf4dV6iHrorWPEM+1Sypw6NqTFStrzly/CroZG/mDP/+KoeqJVHNSL169dw0F2oWefHFF0Pb/Pzzz+5qVU1MSJmH6qO4bNkyN6hDeagBHGoqDt9GTe3q6KzpRajtTEnTXGikq2rWNc3AnXfe6frnaAoWDURo3ry5a4bXfn3mmWeG8jbZ9+VoTz/9tOtbp9HZbdu2jXhN/ZjUJeTSSy91LRrhOLfEhsApk0aLaMI7NcXpQKpRXqLhtpqUzMdBIW1pVUX7nUbVAVxV/GeccYY7kPhTDyRzniqffMoPlTv1/dKweT9P1ZypZk5RoKkTl/JRo5no++B5kyZNishD9blRs5Gfh+rwraZ1BU8aOu/nWbt27VzfMKYQSUkj4xRUau460chN9a3zB3moK4P2be3jmkiUfflf4Xnw7LPPeoUKFXLnFA3g0OjiESNGRGz/ww8/uMBTfZxw5AicMomGgGpUkjosqx+TJrPUQVmFmiv7w1Mn7/CRiAqUdHC96KKLIk5uCg78k1QyX1VpeLz6M+iK1Kch8aqxU975VEOn7TSvixYFAJoPyz9ZJXPwNGbMGK9o0aLuBOXTxIyqIfEnCPX72SnftF+rPKrGU0E+tSSR/P1S89M99dRT7vHEiRNd0OSf8P2+depor8fsy6lTUK4aOb/FQrXEmpxWA4yiO9FrXjvK4NHh5lKZRG3O6keie1W1bt3a1qxZYy1atHDt/LqvFVKnfje6qaza67du3Rpar5vMPvfcc66d/8UXX7QxY8a49WXLlnVt+v5d6JNVgwYNrH///m55+umn3bpjjz3W9Z/T4lOfJt0n8cwzz3T3U1NfCN2NXtuoP04y96+rV6+e3Xnnne5ecuofIurTdMwxx1iBAgXcc/XBUT+7999/3+3PFSpUcDdL9fvicSPkf2mfVN+wdevWufKp+8zdeuutrj+n8lmvvfzyyzZjxoxQHmtfVh4m874cbebMmXbDDTe4457Ko+g+krov4imnnOLuaxp+/0P1a/LLIo7QUQZeOArRV+8adaN5c7iaSp1fFa3ZlzU3k6qiR44cmaIdn6ro1GkqAd12Qc1xAwcOdCO8VBOi6RqiRV+RJnNNU/TVukZrqilE9wBTnmriwLRu+xGO/TrtGa3V3FmgQAF3DPRpSgw1EasPGdKm2iX199Tca/7tkMKnddB8gJUrV46oicfRyaF/jjToQvww2ibSnDlz3JWVrvovuugid/fzxx9/3H7++Wdr06aNdejQIbTtqlWr3JU+V/YpR9ts3rzZRo4caQMHDrRrrrnGXeWXKFHCjeTUiE3VmPz999/WvHlzu+eee1ytQLKPQIym8jVixAibNGmS1alTx9WIqHauSJEiLr+VZ7t27XJ5qBF0iOTXvqnWPX/+/G4ErGqY1q9fb0uWLLG8efO6cnrLLbe4UYja95O5pjOI33//3Z5//nlX03nXXXdZt27dQq8tX77cPvjgA+vRowf5mE44M8fRf/7zH7fj33fffYfdNvwElezNStEUMN18883upHT55ZdHVEVrCLiqopV3ambyq6Il2ZtFwr+/hsQrmDz77LOtY8eO7gA6dOhQFyx1797dBaIKmHTSUvnTiUwImlJS+fLzRycqBZsa9q3mdl3wKBhQM5M/HQb+pWkE3nnnHTfFwLXXXuvySBdCnTt3dhdC5cuXd/u2yqDK7/z5811ZZRqWQ9OFT6dOndz+/sorr7j9tmvXru61atWquUXIx/TB2TlO9u7da+PHj3cnosMFTtFX9ZysIumEr8BJNSWaY0hX+aJ5hR5++GHXJ2LQoEFWunRpd5XvS+agSWXK//4KMN944w3Xv0l5phom9avT6wo89b9qoKJxkE2b5hJS8KS8U5ksWbKkC0CjkYf/mjVrln388cfuQkcXlNpnte8q8Lz66qvdHHZjx451eaa5nFq1auXyjtr34AG9apt0/tB8TZoTq3fv3hHbUBbTyVE29SEV/sgPzUOiPjnvvPPOYbf1h4NrPhiktGbNGteOr7le1LcknPJMc2PRDyelAQMGuL5gX331VYqb8mqkkvJNI8V02x8fQ+WD+/XXX12fJ80/9Mgjj4TWk4fBR8JqniaNpksN+3TsZUn98O666y43tx3lMD4I4+PAH8Wlq3tdNU2ZMsWuuOIKV4UfXpsUXtOkEREPPPCAzZ07NxNTnnVRFR27PXv2uPKkmhA10akpSf1JlH+ayVp9SPSa+uNohnq/PCZ7jWcs/boqVarkrvK3b9/umjvJw9RHwqqf0pYtW9wor+iRsBoh+9JLL7kaEo2qC8e+/G8LRNCuH6p5euyxx9zoTn8UYjLXvscDncPTkW6poB1dJ6TChQu7dap6vvvuu10/HQ3x9g+s4QdnHTTUnKL/dasVHLpjrprsPvzwQzdUProqGv/SiahJkyZ2zjnnuEX9cXTg9TuBn3HGGa6T819//eVubxFdLpNdLH0UNaSeE1VKgwcPdvuomoY///xzN4VIv379XD873w8//OCOmY0aNXKBFFLv+qHBHOr6oY7ehxJe/tif4yRONVlJZ9euXaE7Tmt22/Bqe01EptmYtU30UG8Np9fwcE1QiGCoig5u7NixbpLVUqVKuRnrNVGeaNqLG264IWJb8vJfe/bscfvsVVddddhtw/dn8vBfTMqYPuj6kfUQOKUzzSCs+y5VqVLF9ccZPHiw16tXL3evpaVLl0Zsq6BJs+QSNP2f0aNHe0OHDg20bfiM4BxwD01zDEXPM6T7VenWFkiJE9XR062QjjvuOK9s2bKub5NvxYoVLnjS7VM0S3009uXUg2+tUzCvW/doXqbwWdRT+7vhw4e7ebEWLVqUIWlONgROcaCJ7lTIVQOlK1YFR7qNhX9bAdHBRJ1yCZr+D1f46S86b7Zu3ep9/vnnrka0WrVqoQkZkz0POVGlPyZlPHqa+FPlSveLDL/tj/LUL2d+GQwvi7ogL1as2CEDfhwdAqc4CC/EGnWjO1HrZBU9c7BuuAiu8I9UrAHP119/7e6bFn6jVEYt/YsTVfpiJOyRo+tH1kbglMEnNQVPVEenxBV+xjRxKlj3yx+3APkXJ6r436Im/ObI4Qie0kbXj6yJwCmDJHtzSGq4wj96NHGmL05U8QmeNE+Y7ovYp0+fzE5OwqHrR9ZD4IRMwRX+0aOJMz44UaU/RsIeObp+ZD3M44RMpZv0vvbaazZx4kR3rzRNcql5hZYuXepuEVK9evXQtprn6qGHHnK3E9B9rpJNanOyaJ3mZPJvyPvCCy8EnmhV84ohpfD8WrlypbtVyHvvvefKaPitPzSZaJUqVSyZMddVxkhrPibdjkb5SF5mLAInZDrt/Fo0CahOVJosVDMx6/5puimoLFq0yN0MdNSoUUkZNIVjotX440R1eEzKmHnIw8xF4IRMxxV+cLt377ZevXq5Gb8vvvhiq127trurvLRt29Y2bNhgEyZMsIIFC0acrBQsKQhV7V6yB55HghNV6vnx7bffWsOGDV25SisYD8877du6IbJ/iyQgERE4IUvgCj82NHEis9FMjGRF4IQsiSv8w6OJExmNZmKAwAlIWDRxIiPRTAz8HwInIIHRxImMRjMxkh2BE5CN0MSJjEAzMZIZgRMAICY0EyOZETgBAGJGMzGSFYETAOCo0UyMZMElAQDgqBE0IVkQOAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAgAXz/wA93ZxJXY3FUAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Permutation-based\n", + "plt.figure(figsize=(6,4))\n", + "x = np.arange(len(feat_order))\n", + "plt.bar(x, imp_perm_mean)\n", + "plt.errorbar(x, imp_perm_mean, yerr=imp_perm_std, fmt=\"none\", capsize=4, ecolor=\"black\", zorder=3)\n", + "plt.xticks(x, feat_order, rotation=45, ha=\"right\")\n", + "plt.ylabel(\"Importance (mean)\")\n", + "plt.title(\"Feature Importance (Permutation on Test)\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 7f7a3da9b8b0a70e038f2d3a8167e33212d17c7f Mon Sep 17 00:00:00 2001 From: sinavidi95 Date: Wed, 24 Sep 2025 18:45:13 -0400 Subject: [PATCH 3/3] add feature importance functionalities using lightgbm to preprocessing. --- examples/04_feature_importance.ipynb | 198 ++++++++---------- modularml/preprocessing/__init__.py | 4 + modularml/preprocessing/feature_importance.py | 77 +++++++ 3 files changed, 174 insertions(+), 105 deletions(-) create mode 100644 modularml/preprocessing/feature_importance.py diff --git a/examples/04_feature_importance.ipynb b/examples/04_feature_importance.ipynb index 4dbc765..4c50d0f 100644 --- a/examples/04_feature_importance.ipynb +++ b/examples/04_feature_importance.ipynb @@ -54,7 +54,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "669a024e", "metadata": {}, "outputs": [ @@ -62,8 +62,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Downloading data...\n", - "Download complete.\n", + "Data already downloaded.\n", "Available keys: ['cell_id', 'group_id', 'rpt', 'num_cycles', 'soc', 'soc - coulomb', 'pulse_type', 'voltage', 'q_dchg', 'soh', 'dcir_chg_10', 'dcir_dchg_10', 'dcir_chg_20', 'dcir_dchg_20', 'dcir_chg_30', 'dcir_dchg_30', 'dcir_chg_40', 'dcir_dchg_40', 'dcir_chg_50', 'dcir_dchg_50', 'dcir_chg_60', 'dcir_dchg_60', 'dcir_chg_70', 'dcir_dchg_70', 'dcir_chg_80', 'dcir_dchg_80', 'dcir_chg_90', 'dcir_dchg_90']\n", "Total number of samples: 24048\n" ] @@ -122,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "33cd6f32", "metadata": {}, "outputs": [ @@ -132,7 +131,7 @@ "FeatureSet(label='PulseFeaturesRaw', n_samples=24048)" ] }, - "execution_count": 4, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -213,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "c698d1c7", "metadata": {}, "outputs": [], @@ -234,7 +233,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 8, "id": "3ae08ab9", "metadata": {}, "outputs": [], @@ -253,7 +252,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "504b4b66", "metadata": {}, "outputs": [ @@ -263,7 +262,7 @@ "FeatureSet(label='PulseFeaturesStats', n_samples=24048)" ] }, - "execution_count": 32, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -325,7 +324,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 10, "id": "da7d6952", "metadata": {}, "outputs": [ @@ -333,7 +332,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "FeatureSet(label='filtered', n_samples=12024)\n", + "GraphNode ('filtered')\n", "Filtered to 12024 charge-only samples.\n" ] } @@ -356,7 +355,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 11, "id": "b609296b", "metadata": {}, "outputs": [ @@ -364,7 +363,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "FeatureSet(label='ChargePulseFeatures', n_samples=12024)\n" + "GraphNode ('ChargePulseFeatures')\n" ] } ], @@ -392,15 +391,14 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 12, "id": "663d0904", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", - "from sklearn.ensemble import RandomForestRegressor\n", "from sklearn.model_selection import GroupShuffleSplit\n", - "from sklearn.inspection import permutation_importance\n", + "\n", "\n", "RANDOM_STATE = 42\n", "feat_cols = [\"v_min\",\"v_max\",\"v_mean\",\"v_var\",\"v_skew\",\"v_kurt\"]\n", @@ -418,7 +416,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "ce092a6b", "metadata": {}, "outputs": [ @@ -481,7 +479,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 14, "id": "7329af50", "metadata": {}, "outputs": [ @@ -506,111 +504,88 @@ "\n" ] }, - { - "cell_type": "markdown", - "id": "26a39387", - "metadata": {}, - "source": [ - "4) Fit baseline Random Forest regressor" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "accd1e1d", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Test R^2: 0.961\n" - ] - } - ], - "source": [ - "rf = RandomForestRegressor(\n", - " n_estimators=400,\n", - " random_state=RANDOM_STATE,\n", - " n_jobs=-1\n", - ")\n", - "rf.fit(X_tr, y_tr)\n", - "print(f\"Test R^2: {rf.score(X_te, y_te):.3f}\")\n" - ] - }, { "cell_type": "markdown", "id": "1be929ac", "metadata": {}, "source": [ - "5) Compute feature importances (model-based + permutation)" - ] - }, - { - "cell_type": "markdown", - "id": "a915ddd5", - "metadata": {}, - "source": [ - "**Model-based importance** computed from the average reduction in MSE each feature provides across all splits and trees. Larger values mean the feature is frequently used in informative splits (often near the top of trees)." + "4) Compute feature importances (model-based + permutation)" ] }, { "cell_type": "code", - "execution_count": 26, - "id": "d7ccc2af", + "execution_count": 15, + "id": "b729cbf9", "metadata": {}, "outputs": [], "source": [ - "# (a) Model-based\n", - "imp_model = rf.feature_importances_\n", - "order = np.argsort(imp_model)[::-1]\n", - "feat_order = [feat_cols[i] for i in order]\n", - "imp_model_sorted = imp_model[order]" + "from modularml.preprocessing import FeatureImportance" ] }, { "cell_type": "markdown", - "id": "f68d3f1a", + "id": "804dbbdd", "metadata": {}, "source": [ - "**Permutation-based importance** measures how much test performance drops when we randomly shuffle one feature at a time (breaking its relationship to the target). The bar height is the mean drop across repeats; the error bars show variability across shuffles." + "Constructs a FeatureImportance object configured to use LightGBM" ] }, { "cell_type": "code", - "execution_count": 27, - "id": "31db3e8b", + "execution_count": 19, + "id": "453ccd5a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# (b) Permutation-based (on held-out test)\n", - "perm = permutation_importance(\n", - " rf, X_te, y_te,\n", - " n_repeats=20,\n", - " random_state=RANDOM_STATE,\n", - " n_jobs=-1\n", + "fi = FeatureImportance(\n", + " estimator=\"lgbm\", # choose LightGBM (vs \"rf\" for RandomForest)\n", + " n_estimators=400, # number of trees for LightGBM\n", + " learning_rate=0.05, # shrinkage for boosting\n", + " random_state=42, # reproducibility\n", + " n_jobs=-1 # use all CPU cores\n", ")\n", - "imp_perm_mean = perm.importances_mean[order]\n", - "imp_perm_std = perm.importances_std[order]" + "fi.fit(X, y, feat_cols, groups=groups)" ] }, { "cell_type": "markdown", - "id": "744103cb", + "id": "a915ddd5", "metadata": {}, "source": [ - "6) Plot feature importance" + "**Model-based importance** computed from the average reduction in MSE each feature provides across all splits and trees. Larger values mean the feature is frequently used in informative splits (often near the top of trees)." ] }, { "cell_type": "code", - "execution_count": 31, - "id": "57dffc0a", + "execution_count": 20, + "id": "15b77e1b", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LightGBM] [Info] Auto-choosing col-wise multi-threading, the overhead of testing was 0.000342 seconds.\n", + "You can set `force_col_wise=true` to remove the overhead.\n", + "[LightGBM] [Info] Total Bins 1530\n", + "[LightGBM] [Info] Number of data points in the train set: 12024, number of used features: 6\n", + "[LightGBM] [Info] Start training from score 82.529598\n" + ] + }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAGGCAYAAACNCg6xAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAQ3FJREFUeJzt3QucTfX+//GP+yW5TkzJSaVyv0QklS6kk4quuo4UleimOhERlWvHIRy6qROnKKXL0dFFFHGSkUhRKrdikBiRS6z/4/39/de29549rBkzs2dmv56Px2L22mvv/d3fvfZen/X9fr7fVcTzPM8AAABwWEUPvwkAAACEwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQDyyLp166x06dL22WefxbsoNmfOHCtSpIj7P6teeukl99jVq1cfdltt17NnTytIYr2/M8880/72t7/FtVzIHwicUCj4P3Sxlt69e+fKa86fP98ee+wx27Ztm+XX+li0aJEVVP/85z/d+yhMBg0aZC1atLBWrVqF1t1yyy3usypfvrz98ccfGR7z/fffh/blp556Ko9LDN/DDz9s48aNs40bN8a7KIiz4vEuAJDTB6YTTzwxYl39+vVzLXAaOHCgO/BVrFgxV14jkSlwSkpKcvVbGGzevNn+9a9/uSVa8eLFbdeuXfbuu+/atddeG3Hfv//9b9dKtXv37jwsLaJ16NDBBbfaL/U7g8RF4IRC5a9//as1a9bMCrKdO3faUUcdZYlKAUTZsmWtsJk8ebILkC677LIM95UqVcq1Qr366qsZAqdXXnnF2rdvb2+88UYelhbRihYtaldffbW9/PLL7oRJLYBITHTVIaH897//tXPOOccFJkcffbQ7IC1fvjxim6VLl7pWjpNOOsmd6ScnJ9utt95qv/76a2gbddE99NBD7m+1cPldKcqJ0KK/Y3Uzab0eG/48WvfNN9/YDTfcYJUqVbKzzz474mDbtGlTK1OmjFWuXNmuu+46lyeTHXpP5cqVs7Vr19qll17q/q5evbrrfpBly5bZBRdc4OrmhBNOcAfsWN1/n376qd1xxx1WpUoVdwaekpJiv/32W4bX05l5vXr1XFBw3HHHWY8ePTJ0a5533nmuRTA1NdXOPfdcFzA98sgjVrNmTfe5fPLJJ6G61baydetWe/DBB61BgwbuPagMCpi/+uqrmDk8r732mj355JN2/PHHu8/zwgsvtFWrVmUo7+eff26XXHKJ+wxUBw0bNrTRo0dHbLNixQp38NRnoedSkP7OO+8Eqv+33nrLddOpzLHo89f+GV5HX3zxheuq032x/Pjjj3bNNde48qjulIczY8aMDNutX7/eOnbs6N5X1apV7f7777c9e/bEfE7Vw8UXX2wVKlRwz9m6descyclSy9lpp53m6k37tPajcGvWrLG77rrLbaP9XfuX3lt0HtW+fftc4HLKKae459J2+s58+OGH2fqstJ9pv9drah954okn7MCBAzHfQ9u2bV05lyxZcsT1gYKLFicUKtu3b7ctW7ZErFN3j0yaNMk6d+5s7dq1s2HDhrmWjfHjx7sf3S+//NIdrEU/wDogdenSxQVN+mF99tln3f//+9//3MH4yiuvtO+++861EPzjH/8IvcYxxxzjumSySgcIHQgGDx5snue5dTrYP/roo64FomvXru55x4wZ4wIMlTc73YP79+93QYaeY/jw4e5gpsRdHVD79u1rN954o3tvEyZMcAFRy5YtM3R9anu9toK+lStXujrUwcQPVET36eDWpk0b6969e2g7BQI6CJcoUSL0fApIVSYFhTfddJNVq1bNBUl33323CzJULtF60WejIER1prKlpaXZM8884w7wCkAVpIUbOnSoay1QsKX9Q+9b71MBgk+fuYLJY4891u699173uX/77bf2n//8x90Wff5qFVKwqbw51ZmCMgUkag264oorMq13Hez13lUXmVG933nnnfbmm2+6QF0UvNauXdtOP/30DNvrfZ911lluP77nnntcAKFuwMsvv9ymTZsWKo/yphQsKmDWdqoffRc+/vjjDM+pdfosFNgMGDDA1duLL77oAou5c+da8+bNLTsUAE+dOtW9vgJpBdUKzhYuXBjqSlf9qPtb+4ECGAVM2me0L+hz9VshtW8NGTLEfSdUnvT0dJfLt3jxYhfYZOWzUr7S+eefb3/++WdoO33XFUTFonoR7cNNmjTJVl2gEPCAQuDFF19UtBFzkR07dngVK1b0unXrFvG4jRs3ehUqVIhYv2vXrgzP/+qrr7rn+vTTT0PrRowY4db99NNPEdvqttarTNG0fsCAAaHb+lvrrr/++ojtVq9e7RUrVsx78sknI9YvW7bM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1NLkV86hLnsAAAASQ3p6umtU8WOEQ0m4wMnvnlPQROAEAAB8QVJ4SA4HAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICAEu5adXmhZu8ZluhWD20f7yIAAFA4W5zGjRtnNWvWtNKlS1uLFi1s4cKFmW573nnnuYvwRS/t23OgBgAAhTxwmjp1qvXq1csGDBhgixcvtkaNGlm7du1s06ZNMbd/8803bcOGDaHl66+/tmLFitk111yT52UHAACJJe6B08iRI61bt27WpUsXq1u3rk2YMMHKli1rEydOjLl95cqVLTk5ObR8+OGHbnsCJwAAUKgDp71791pqaqq1adPmYIGKFnW3FyxYEOg5XnjhBbvuuuvsqKOOinn/nj17LD09PWIBAAAocIHTli1bbP/+/VatWrWI9bq9cePGwz5euVDqquvatWum2wwZMsQqVKgQWmrUqJEjZQcAAIkn7l11R0KtTQ0aNLDmzZtnuk2fPn1s+/btoWXdunV5WkYAAFB4xHU6gqSkJJfYnZaWFrFet5W/dCg7d+60KVOm2KBBgw65XalSpdwCAABQoFucSpYsaU2bNrVZs2aF1h04cMDdbtmy5SEf+/rrr7v8pZtuuikPSgoAAJAPJsDUVASdO3e2Zs2auS63UaNGudYkjbKTlJQUq169ustViu6m69ixo1WpUiVOJQcAAIkm7oFTp06dbPPmzda/f3+XEN64cWObOXNmKGF87dq1bqRduJUrV9q8efPsgw8+iFOpAQBAIirieZ5nCUTTEWh0nRLFy5cvnyuvwSVXuOQKAKBwxgYFelQdAABAXiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAoKAETuPGjbOaNWta6dKlrUWLFrZw4cJDbr9t2zbr0aOHHXvssVaqVCk79dRT7b333suz8gIAgMRVPJ4vPnXqVOvVq5dNmDDBBU2jRo2ydu3a2cqVK61q1aoZtt+7d6+1bdvW3Tdt2jSrXr26rVmzxipWrBiX8gMAgMQS18Bp5MiR1q1bN+vSpYu7rQBqxowZNnHiROvdu3eG7bV+69atNn/+fCtRooRbp9YqAACAQt1Vp9aj1NRUa9OmzcHCFC3qbi9YsCDmY9555x1r2bKl66qrVq2a1a9f3wYPHmz79+/Pw5IDAIBEFbcWpy1btriARwFQON1esWJFzMf8+OOP9vHHH9uNN97o8ppWrVpld911l+3bt88GDBgQ8zF79uxxiy89PT2H3wkAAEgUcU8Oz4oDBw64/KZnn33WmjZtap06dbK+ffu6Lr7MDBkyxCpUqBBaatSokadlBgAAhUfcAqekpCQrVqyYpaWlRazX7eTk5JiP0Ug6jaLT43x16tSxjRs3uq6/WPr06WPbt28PLevWrcvhdwIAABJF3AKnkiVLulajWbNmRbQo6bbymGJp1aqV657Tdr7vvvvOBVR6vlg0ZUH58uUjFgAAgALXVaepCJ577jn717/+Zd9++611797ddu7cGRpll5KS4lqMfLpfo+ruvfdeFzBpBJ6Sw5UsDgAAUKinI1CO0ubNm61///6uu61x48Y2c+bMUML42rVr3Ug7n/KT3n//fbv//vutYcOGbh4nBVEPP/xwHN8FAABIFEU8z/MsgWhUnZLEle+UW912NXvPsES3emj7eBcBAIAcjw0K1Kg6AACAeCJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIIUOI0bN85q1qxppUuXthYtWtjChQsz3fall16yIkWKRCx6HAAAQKEPnKZOnWq9evWyAQMG2OLFi61Ro0bWrl0727RpU6aPKV++vG3YsCG0rFmzJk/LDAAAElPcA6eRI0dat27drEuXLla3bl2bMGGClS1b1iZOnJjpY9TKlJycHFqqVauWp2UGAACJKa6B0969ey01NdXatGlzsEBFi7rbCxYsyPRxv//+u51wwglWo0YN69Chgy1fvjyPSgwAABJZXAOnLVu22P79+zO0GOn2xo0bYz7mtNNOc61Rb7/9tk2ePNkOHDhgZ511lq1fvz7m9nv27LH09PSIBQAAoEB21WVVy5YtLSUlxRo3bmytW7e2N99804455hh75plnYm4/ZMgQq1ChQmhRKxUAAECBC5ySkpKsWLFilpaWFrFet5W7FESJEiWsSZMmtmrVqpj39+nTx7Zv3x5a1q1blyNlBwAAiSeugVPJkiWtadOmNmvWrNA6db3ptlqWglBX37Jly+zYY4+NeX+pUqXcKLzwBQAAIDuKW5xpKoLOnTtbs2bNrHnz5jZq1CjbuXOnG2Un6parXr2663KTQYMG2Zlnnmm1atWybdu22YgRI9x0BF27do3zOwEAAIVd3AOnTp062ebNm61///4uIVy5SzNnzgwljK9du9aNtPP99ttvbvoCbVupUiXXYjV//nw3lQEAAEBuKuJ5nmcJRKPqlCSufKfc6rar2XuGJbrVQ9vHuwgAAOR4bFDgRtUBAADEC4ETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQG4HTpMmTbJWrVrZcccd5yagFE1eqYvvAgAAFEbZCpzGjx/vZvy+5JJL3OzduuyJVKxY0QVPAAAAhVG2AqcxY8bYc889Z3379nUX6fXpsim6bhwAAEBhlK3A6aeffrImTZrEvKCurjMHAABQGGUrcDrxxBNtyZIlGdbrGnN16tTJiXIBAAAUjov8Kr+pR48etnv3btOl7hYuXGivvvqqDRkyxJ5//vmcLyUAAEBBDZy6du1qZcqUsX79+tmuXbvshhtucKPrRo8ebdddd13OlxIAAKCgBk5y4403ukWB0++//25Vq1bN2ZIBAAAUhsBJyeF//vmnnXLKKVa2bFm3yPfff28lSpSwmjVr5nQ5AQAACmZy+C233GLz58/PsP7zzz939wEAABRG2QqcvvzySzdreLQzzzwz5mg7AACAhA2cihQpYjt27Miwfvv27aFZxAEAAAqbbAVO5557rpt6IDxI0t9ad/bZZ+dk+QAAAAp2cviwYcNc8HTaaafZOeec49bNnTvX0tPT7eOPP87pMgIAABTcFqe6deva0qVL7dprr7VNmza5bruUlBRbsWKF1a9fP+dLCQAAUJDncdKEl4MHD87Z0gAAABTGwGnbtm3uUitqcTpw4EDEfWp9AgAAKGyyFTi9++67btZwzRhevnx5N8rOp78JnAAAQGGUrRynBx54wG699VYXOKnl6bfffgstW7duzflSAgAAFNTA6eeff7Z77rkndKkVAACARJCtwKldu3a2aNGinC8NAABAYctxat++vT300EP2zTffWIMGDdyFfcNdfvnlOVU+AACAgh04devWzf0/aNCgDPcpOTyrl10ZN26cjRgxwjZu3GiNGjWyMWPGWPPmzQ/7uClTptj1119vHTp0sLfeeitLrwkAAJAnXXWafiCzJatB09SpU61Xr142YMAAW7x4sQuc1BWoaQ4OZfXq1fbggw+GZi4HAADIl4FTTho5cqRrwerSpYubkXzChAku6XzixImZPkbBmaZDGDhwoJ100kl5Wl4AAJC4sj0B5s6dO+2TTz6xtWvX2t69eyPu04i7IPS41NRU69OnT2hd0aJFrU2bNrZgwYJMH6cuwqpVq9ptt93mrpF3KHv27HGLT9fTAwAAyLPA6csvv7RLLrnEdu3a5QKoypUr25YtW1xLkQKaoIGTHqPWo2rVqkWs121d9y6WefPm2QsvvGBLliwJ9BpDhgxxLVMAAABx6aq7//777bLLLnMTXpYpU8b+97//2Zo1a6xp06b21FNPWW7RxYRvvvlme+655ywpKSnQY9SatX379tCybt26XCsfAAAo3LLV4qTWnmeeecZ1qxUrVsx1hSnXaPjw4da5c2e78sorAz2Pgh89Pi0tLWK9bicnJ2fY/ocffnBJ4QrafP518ooXL24rV660k08+OeIxpUqVcgsAAEBcWpw0b5OCJlHXnPKcpEKFCllq0SlZsqRrpZo1a1ZEIKTbLVu2zLB97dq1bdmyZS5w8xfNGXX++ee7v2vUqJGdtwMAAJB7LU5NmjSxL774wk455RRr3bq19e/f3+UrTZo0yerXr5+l59JUBGqlatasmZu7adSoUS5vSqPsRBcMrl69ustVKl26dIbnr1ixovs/q68LAACQJ4HT4MGDXb6RPPnkky646d69uwuklLidFZ06dbLNmze74EsTYDZu3NhmzpwZShhXa5bfugUAABBPRTzP8yyBaDoCdSkqUbx8+fK58ho1e8+wRLd6aPt4FwEAgByPDbLVlHPBBRfYtm3bYr6w7gMAACiMshU4zZkzJ8Okl7J79+7DTkgJAACQEDlOS5cuDf39zTffuJwknyayVG6SErkBAAAs0QMnJW4XKVLELbG65DQZ5pgxY3KyfAAAAAUzcPrpp59MueSa7HLhwoV2zDHHRMzJpDmdNKElAACAJXrgdMIJJ9i+ffvcvEtVqlRxtwEAABJF0ezMGj59+vTcKQ0AAEBhG1XXoUMHe+utt3K+NAAAAIVt5nDNED5o0CD77LPP3LXmjjrqqIj777nnnpwqHwAAQMEOnHRZFV0jLjU11S3hNOKOwAkAABRG2QqcNLoOAAAg0Rzx1XM1PUGCXe4OAAAkqGwHTi+//LI1aNDATXqppWHDhjZp0qScLR0AAEBB76obOXKkPfroo9azZ09r1aqVWzdv3jy78847bcuWLXb//ffndDkBAAAKZuCky6qMHz/eUlJSQusuv/xyq1evnj322GMETgAAoFDKVlfdhg0b7KyzzsqwXut0HwAAQGGUrcCpVq1a9tprr2VYP3XqVDfHEwAAQGGUra66gQMHWqdOnezTTz8N5ThpMsxZs2bFDKgAAAAStsXpqquuss8//9ySkpLcpVe06O+FCxfaFVdckfOlBAAAKKgtTqJLrUyePDlnSwMAAFAYA6f9+/fb9OnT7dtvv3W369at6y7+W7x4tp8SAAAgX8tWlLN8+XI3/cDGjRvttNNOc+uGDRtmxxxzjL377rtWv379nC4nAABAwcxx6tq1q5uzaf369bZ48WK3rFu3zs0efvvtt+d8KQEAAApqi9OSJUts0aJFVqlSpdA6/f3kk0/aGWeckZPlAwAAKNgtTqeeeqqlpaVlWL9p0yY3xxMAAEBhlK3AaciQIXbPPffYtGnTXHedFv193333uVyn9PT00AIAAJDQXXWXXnqp+//aa6+1IkWKuL89z3P/X3bZZaHbuk+j7wAAABI2cJo9e3aOFmLcuHE2YsQIN0qvUaNG7iLCzZs3j7ntm2++aYMHD7ZVq1bZvn373CVeHnjgAbv55ptztEwAAAA5Eji1bt3acoqub9erVy+bMGGCtWjRwkaNGmXt2rWzlStXWtWqVTNsX7lyZevbt6/Vrl3bSpYsaf/5z3+sS5cubls9DgAAILcU8fw+tizavXu3LV261CWEHzhwIOI+zfEUlIIljcQbO3asu63nqlGjht19993Wu3fvQM9x+umnW/v27e3xxx8/7LbKu6pQoYJt377dypcvb7mhZu8ZluhWD20f7yIAABBIVmKDbLU4zZw501JSUmzLli0Z7stKXtPevXstNTXV+vTpE1pXtGhRa9OmjS1YsOCwj1fM9/HHH7vWKSWlAwAA5LtRdWoNuuaaa2zDhg2uhSh8yUoyuAIvbV+tWrWI9bqtfKfMKCIsV66c66pTS5Nyotq2bRtz2z179kSM8mOkHwAAyK5stThpDiflJUUHPHnl6KOPdpNw/v777zZr1ixXlpNOOsnOO++8mFMnDBw4MC7lBAAAhUu2WpyuvvpqmzNnzhG/eFJSkhUrVizDZJq6nZycnOnj1J2niTYbN27sRtSpPAqQYlE3oFqo/EWXhgEAAMizFiclcqurbu7cudagQQMrUaJExP2aHDMIdbU1bdrUtRp17NjRrVN3n2737NkzcHn0GHXJxVKqVCm3AAAAxCVwevXVV+2DDz6w0qVLu5YnfxJM0d9BAydRN1vnzp2tWbNmbu4mTUewc+dON8WAKAm9evXqoRYl/a9tTz75ZBcsvffeezZp0iQbP358dt4KAABA7gZOmkdJeUOaLkDdZkeiU6dOtnnzZuvfv79LCFf3m0bt+flTa9eujXgNBVV33XWXu8xLmTJl3HxOkydPds8DAACQ7+Zx0iSUX3zxhWv1KWiYxylvMI8TAKAwxgbZai5S15pm/AYAAEgk2eqq09xLw4cPt/fff98aNmyYITl85MiROVU+AACAgh04LVu2zJo0aeL+/vrrr3O6TAAAAIUncJo9e3bOlwQAAKAwBU5XXnnlYbfRdARvvPHGkZQJAACg4AdOyjgHAABIVFkKnF588cXcKwkAAEA+d2SzVwIAACQQAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAoCAFTuPGjbOaNWta6dKlrUWLFrZw4cJMt33uuefsnHPOsUqVKrmlTZs2h9weAACg0AROU6dOtV69etmAAQNs8eLF1qhRI2vXrp1t2rQp5vZz5syx66+/3mbPnm0LFiywGjVq2EUXXWQ///xznpcdAAAkliKe53nxLIBamM444wwbO3asu33gwAEXDN19993Wu3fvwz5+//79ruVJj09JSTns9unp6VahQgXbvn27lS9f3nJDzd4zLNGtHto+3kUAACCQrMQGcW1x2rt3r6WmprrutlCBihZ1t9WaFMSuXbts3759Vrly5Zj379mzx1VI+AIAAJAdcQ2ctmzZ4lqMqlWrFrFetzdu3BjoOR5++GE77rjjIoKvcEOGDHFRpL+oNQsAAKBA5jgdiaFDh9qUKVNs+vTpLrE8lj59+rimN39Zt25dnpcTAAAUDsXj+eJJSUlWrFgxS0tLi1iv28nJyYd87FNPPeUCp48++sgaNmyY6XalSpVyCwAAQIFucSpZsqQ1bdrUZs2aFVqn5HDdbtmyZaaPGz58uD3++OM2c+ZMa9asWR6VFgAAJLq4tjiJpiLo3LmzC4CaN29uo0aNsp07d1qXLl3c/RopV716dZerJMOGDbP+/fvbK6+84uZ+8nOhypUr5xYAAIBCGzh16tTJNm/e7IIhBUGNGzd2LUl+wvjatWvdSDvf+PHj3Wi8q6++OuJ5NA/UY489luflBwAAiSPu8zjlNeZxyhvM4wQAKCgKzDxOAAAABQmBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABBQ8aAbAnmpZu8ZluhWD20f7yIAAKLQ4gQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEEJnMaNG2c1a9a00qVLW4sWLWzhwoWZbrt8+XK76qqr3PZFihSxUaNG5WlZAQBAYotr4DR16lTr1auXDRgwwBYvXmyNGjWydu3a2aZNm2Juv2vXLjvppJNs6NChlpycnOflBQAAiS2ugdPIkSOtW7du1qVLF6tbt65NmDDBypYtaxMnToy5/RlnnGEjRoyw6667zkqVKpXn5QUAAIktboHT3r17LTU11dq0aXOwMEWLutsLFizIsdfZs2ePpaenRywAAAAFKnDasmWL7d+/36pVqxaxXrc3btyYY68zZMgQq1ChQmipUaNGjj03AABILHFPDs9tffr0se3bt4eWdevWxbtIAACggCoerxdOSkqyYsWKWVpaWsR63c7JxG/lQpEPBQAACnTgVLJkSWvatKnNmjXLOnbs6NYdOHDA3e7Zs2e8igUUGjV7z4h3EfKF1UPbx7sIAAqRuAVOoqkIOnfubM2aNbPmzZu7eZl27tzpRtlJSkqKVa9e3eUp+Qnl33zzTejvn3/+2ZYsWWLlypWzWrVqxfOtAACABBDXwKlTp062efNm69+/v0sIb9y4sc2cOTOUML527Vo30s73yy+/WJMmTUK3n3rqKbe0bt3a5syZE5f3AAAAEkdcAydRt1xmXXPRwZBmDPc8L49KBgAAkGCj6gAAAHIKgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEVD7ohACSimr1nWKJbPbR9vIsA5BsETgCAXEXwSfBZmNBVBwAAEBCBEwAAQEHqqhs3bpyNGDHCNm7caI0aNbIxY8ZY8+bNM93+9ddft0cffdRWr15tp5xyig0bNswuueSSPC0zAAB5he5OyzfdnXFvcZo6dar16tXLBgwYYIsXL3aBU7t27WzTpk0xt58/f75df/31dtttt9mXX35pHTt2dMvXX3+d52UHAACJJe6B08iRI61bt27WpUsXq1u3rk2YMMHKli1rEydOjLn96NGj7eKLL7aHHnrI6tSpY48//ridfvrpNnbs2DwvOwAASCxxDZz27t1rqamp1qZNm4MFKlrU3V6wYEHMx2h9+PaiFqrMtgcAACgUOU5btmyx/fv3W7Vq1SLW6/aKFStiPkZ5ULG21/pY9uzZ4xbf9u3b3f/p6emWWw7s2WWJ7kjrlzqkDnMK9XjkqMMjRx0eudw8bvvP7XlewUgOz01DhgyxgQMHZlhfo0aNuJQnUVQYFe8SFHzUYc6gHo8cdXjkqMOCUYc7duywChUq5N/AKSkpyYoVK2ZpaWkR63U7OTk55mO0Pivb9+nTxyWf+w4cOGBbt261KlWqWJEiRaywUdSsoHDdunVWvnz5eBenwKIejxx1eOSow5xBPR65wl6Hnue5oOm444477LZxDZxKlixpTZs2tVmzZrmRcX5go9s9e/aM+ZiWLVu6+++7777Qug8//NCtj6VUqVJuCVexYkUr7LRjF8adO69Rj0eOOjxy1GHOoB6PXPlCXIeHa2nKN111ag3q3LmzNWvWzM3dNGrUKNu5c6cbZScpKSlWvXp11+Um9957r7Vu3dr+/ve/W/v27W3KlCm2aNEie/bZZ+P8TgAAQGEX98CpU6dOtnnzZuvfv79L8G7cuLHNnDkzlAC+du1aN9LOd9ZZZ9krr7xi/fr1s0ceecRNgPnWW29Z/fr14/guAABAIoh74CTqlsusa27OnDkZ1l1zzTVuQUbqltRkotHdk8ga6vHIUYdHjjrMGdTjkaMODyriBRl7BwAAgPjPHA4AAFBQEDgBAAAEROAEAAAQEIETAABAQAROBZQmCgUAAHmLwKmAefnll93U8OFzWyF7GFCadQTsOYv6BAoejr4FyFNPPWV33nmnffXVV/EuSoH22Wefuf8L47UKc5sfsP/3v/+Nd1EKpE8++ST096BBg2z06NFxLQ8SV6ygnZPJYAicCogFCxbY6tWrbfr06W52dWSPLtHTvXv3eBejQPv555/d5Y7GjRsX76IUKJs2bbKrrrrK2rVr5661OXz4cPc3sufNN990l976+OOPbfv27fEuToELmvyToB9//NG+++479zcnk8EQOBUA7777rt1xxx02Y8YMO/744906mvizR5fy+eWXXywtLY2zq4D2798fcdu/duSrr75qqampcStXQVO1alWbO3euOwnStTXnz59vdevWtT///DPeRStw+vTpY7fccotNnjzZBZ+PPvqoLVu2LN7FKjD8oEn1eP7559u5555rF110ka1ZsybeRSsQCJwKgL/85S9Wr149dy2/9957L7TjEzxlXc2aNd1ZVXp6uvs/OihARsWKFXP/T5s2zV2AWzp06GAlSpSwDz74wN1mX8xceN0oaNJ+d/TRR7trbSp4L168eIb6I6jPnIL1xYsX2/vvv29ffvmlC54+/PBDe/rpp23p0qXxLl6+Fv5799prr7kWeLXajR8/3p1MXnrppdRhQblWHQ6tUaNG7hpBOoDpLD8pKcm6dOkSCp5IFD80/aB+8cUX7gLRxx57rGt10gFMF4j2g4LwAxbN1RnpIHXttdfaBRdc4K4TqYtz33XXXe6sX0GUWk7YFzMKH8jx8MMP2/Lly12rk+pKB6m//vWv7qLm4fWmg1v0fon/owP8vHnzrFKlSnbGGWe4ddoX5bHHHnPf3bvvvtsaNGgQ55LmL3v27HHXmPP3qzfeeMN+/fVXt09effXVbl3btm2tdevWdsMNN7jjDHWYOX7l8ikd6HWwUvS/e/duq127tv3tb39zLU/PP/+8vfTSS247/eBydpq5rVu3uj78LVu2uB+De++9177//nvr3bu3XXjhhdavXz83UlFnXkLQ9H+iW0BOO+00O/HEE11T/vr16+2yyy6zk08+2f3oKmfs999/J2iKwd+fvvnmG3fAV9dIw4YNXZ7i1KlT7euvv3b5Yn53nbrk9f1GbDt27HAtn2pxUs6nT8HTwIEDXfenku5/+OGHuJYzP1EwFD6Y47fffrPbbrvNevTo4dIWRMeQcuXK2aeffmqlS5e2m266ydUxMqGL/CJ/6d27t3faaad5SUlJ3rnnnut17drV27Fjh7tvyZIl3s033+ydc8453rhx4+Jd1ALn+++/9/761796l1xyiffoo4961157rVejRg2vffv23v79++NdvHxn+fLl3q+//ur+/u9//+vVr1/fe/nll72nn37aq1SpkqvLatWqec888wz1l4nBgwd7l156qXfllVd6O3fujLhv3rx5bv+rVauWd+aZZ3onn3yyt2/fvriVtSB47rnnvGOOOcb729/+5q1Zsybivpdeesm74YYb2BfDPPXUU97u3bvd3/6+9d1333mNGjXymjVr5q1fv96tO3DggPv/999/944//njvpptuimOp8zcCp3xmyJAhXnJysvfJJ5+4HblHjx5e2bJl3Y/u9u3b3TZfffWVO9DfcccdoZ0dkX755Rdv69at7kdAwg9GqmP9YPgUlPr1SH0e9M4773i1a9f2Onfu7AJO6dOnjzdgwAD398cff+zuK1KkiNelS5c4lzb/iD5oK9BUHSnA/OabbzJsrwPXgw8+6OrV30///PPPPCtvfqfA3T+4+/7xj3941atX9x555BFv7dq1MR+X6MFT9Pt/8sknvbFjx4Z+ExU8nXDCCd7555/vbdy4MeL3748//mAfPAQCp3xkxYoV3tlnn+29++677vb777/vHXXUUV5KSopXp04d1zritzzpQOZ/MTjYZzzDb968udewYUPvvPPO81avXu3W79271/3/yiuvuDN7/7Yv0X9oY+1Hzz77rHfFFVd45cuX91599VVv1KhR7od22bJl7v4NGzZ4c+bM4Uc2Bp3g6ADkB6EKnu666y5v06ZNh6xzWpwOGjhwoNeqVSuvQoUK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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAGGCAYAAACNCg6xAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAP7BJREFUeJzt3QmcVfP/x/FP+0a7NpKI9oX4JS3aFBItfvQrijZRqEhFUlkiREjxC0lKWULya9+JlKJFiFZaVGq0b+f/eH/9z3XvLHWapmbu3Nfz8bjN3HPO3M79zpl73ue7nQye53kGAACAE8p44k0AAAAgBCcAAICACE4AAAABEZwAAAACIjgBAAAERHACAAAIiOAEAAAQEMEJAAAgIIITAABAQAQnIIZlyJDB+vfvf9I/t27dOvezo0aNOuG2derUsQoVKlg0OZn3ByC2EJyAVKaTs07SeixYsCDBet0VqXjx4m79DTfckCr7iMTNmTPH/V4++OADi1Zjx461F198MbV3A4gaBCcgjciePbs7icU3d+5c27Rpk2XLli1V9gvpG8EJODkEJyCNuP766+3999+3I0eOJDixVa1a1YoUKZJq+4b0Z+/evam9C0BUIjgBacR//vMf27Fjh02fPj207NChQ64ZqFWrVkme/B544AHXlKcaqdKlS9tzzz3nmvfCHTx40Lp3727nnHOOnX322XbjjTe6WqzE/Pbbb9auXTsrXLiwe83y5cvbm2++ecrvb8mSJXbVVVdZjhw5rGTJkjZixIiI9Xqv/fr1cyExT548litXLqtVq5bNnj07wWu99957bju9l9y5c1vFihVt6NChEdvs2rXLunXrFiqbUqVK2TPPPGPHjh1LsN0dd9zh/s+8efNa27Zt3bLkUp8xNd/99NNPdtttt7nXVbk/+uij7veyceNGu+mmm9x+Kww///zziTb/jR8/3h5++GG3jcpCvzP9bHwK2yoLlWvBggXd/6nfYTi9v7POOst++eUXF9BVbq1bt3b9zyZPnmzr168PNRdfcMEFJ/X78PuD6bh7/fXX7aKLLnLlfcUVV9g333yTYH9Xr15tt9xyiysT7bOO2UceeeSMHINASsicIq8C4JTphFW9enUbN26cXXfddW7Z//73P9u9e7e1bNnSXnrppYjtdRLWyVQnsvbt21uVKlVs6tSp1rNnT3fieeGFF0LbdujQwcaMGeMCmMLLrFmzrHHjxgn2YevWrXbllVe6E2HXrl3dyU37oNePi4tzQSQ5/vzzT3fC1glTAXHChAl29913W9asWd0JUvT6I0eOdOs7duxof/31l73xxhvWqFEjW7RokXt/omCpberXr++CkPzwww/2xRdf2P333++e79u3z66++mpXDnfddZedf/759uWXX1qfPn1s8+bNoaYplaFCjPqWde7c2cqWLWsTJ0504elU3Xrrre71nn76aRdOnnjiCcufP7+99tprVq9ePbfv7777rj344IMuZNSuXTvi55988kn3e+jVq5dt27bN7XODBg1s2bJlLnD4/ePuvPNO9/ODBg1yvz8FSJXF0qVLXRD0qSZTZVmzZk0XcnLmzOlCmY4vhWj/eFHAOpnfR3jNqLZReWu/Bw8ebM2bN7dff/3VsmTJ4rb5/vvvXfjS806dOrljXmFu0qRJ7v2ezmMQSDEegFT11ltvqXrI++abb7xXXnnFO/vss719+/a5df/+97+9unXruu9LlCjhNW7cOPRzH3/8sfu5J554IuL1br75Zi9DhgzemjVr3PNly5a57e65556I7Vq1auWWP/bYY6Fl7du394oWLept3749YtuWLVt6efLkCe3X2rVr3c9q30/k6quvdts+//zzoWUHDx70qlSp4hUqVMg7dOiQW3bkyBG3PNyff/7pFS5c2GvXrl1o2f333+/lzp3bbZ+Uxx9/3MuVK5f3008/RSzv3bu3lylTJm/Dhg0RZTh48ODQNnrdWrVqBXp/s2fPdtu9//77oWUqTy3r1KlTxGued9557vfy9NNPR7y/HDlyeG3btk3wmueee64XFxcXWj5hwgS3fOjQoe65yk3lV6FCBW///v2h7T777DO3Xb9+/ULL9Ppapvcfn44pHVvxBf19+MdCgQIFvJ07d4aWf/LJJ275pEmTQstq167tju/169dHvO6xY8dO+hgEUgtNdUAaohqZ/fv322effeau3vU1qWa6zz//3DJlymT33XdfxHI13akmRVfp/nYSf7v4V+76mQ8//NCaNGnivt++fXvooVoG1Ux8++23yXpfmTNndjURPtU06blqUtSEJ3ovWi5qTtu5c6erJbn88ssj/l/VoqiJMrxJM7HmK9Vs5MuXL+J9qMbm6NGjNm/evFDZaN9U++XTftx77712qlTLF/6aeh8q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r9OzZ087cuRIxDZz5syxyy67zLJly2alSpWyUaNGnZH3CAAA0o/Mqfmfz50717p06eLCk4LOww8/bA0bNrRVq1ZZrly5Qtt17NjRBg4cGHqugOQ7evSoC01FihSxL7/80jZv3mxt2rSxLFmy2FNPPeW2Wbt2rdtGgevdd9+1mTNnWocOHaxo0aLWqFGjM/yukdIu6D3ZYtW6pxun9i4AQExJ1eA0ZcqUiOeqBVKN0ZIlS6x27doRQUnBKDHTpk1zQWvGjBlWuHBhq1Klij3++OPWq1cv69+/v2XNmtVGjBhhJUuWtOeff979TNmyZW3BggX2wgsvEJwAAEB09nHavXu3+5o/f/6I5aolKliwoFWoUMH69Olj+/btC61buHChVaxY0YUmn8JQXFycrVy5MrRNgwYNIl5T22g5AABAVNQ4hTt27Jh169bNatSo4QKSr1WrVlaiRAkrVqyYff/9964mSf2gPvroI7d+y5YtEaFJ/Odad7xtFK72799vOXLkiFh38OBB9/BpOwAAgDQTnNTXacWKFa4JLVynTp1C36tmSf2S6tevb7/88otddNFFp63T+oABA07LawMAgOiVJprqunbtap999pnNnj3bzjvvvONuW61aNfd1zZo17qv6Pm3dujViG/+53y8qqW1y586doLZJ1ByoZkP/sXHjxlN8hwAAID1I1eDkeZ4LTRMnTrRZs2a5DtwnsmzZMvdVNU9SvXp1W758uW3bti20zfTp010oKleuXGgbjaQLp220PDGaskA/H/4AAADImNrNc2PGjLGxY8e6uZzUF0kP9TsSNcdphJxG2a1bt84+/fRTN9WARtxVqlTJbaPpCxSQbr/9dvvuu+9s6tSp1rdvX/faCkCiaQh+/fVXe+ihh2z16tX26quv2oQJE6x79+6p+fYBAECUSdXgNHz4cNcUpkkuVYPkP8aPH+/WayoBTTOgcFSmTBl74IEHrEWLFjZp0qTQa2TKlMk18+mrapBuu+02F67C531STdbkyZNdLVPlypXdtAQjR45kKgIAABA9ncPVVHc8xYsXd5NknohG3X3++efH3UbhbOnSpSe9jwAAAGmqczgAAEA0IDgBAAAERHACAAAIiOAEAAAQEMEJAAAgIIITAABAQAQnAACAgAhOAAAAARGcAAAAAiI4AQAABERwAgAAiIZ71QFIXRf0nmyxat3TjVN7FwBEIWqcAAAAAiI4AQAABERwAgAACIjgBAAAEBDBCQAAICCCEwAAQEAEJwAAgIAITgAAAAERnAAAAAIiOAEAAAREcAIAAAiI4AQAABAQwQkAACAgghMAAEBABCcAAICACE4AAAABEZwAAAACIjgBAAAERHACAAAIiOAEAAAQEMEJAAAgIIITAABAQAQnAACAgAhOAAAAARGcAAAAAiI4AQAABERwAgAACIjgBAAAEBDBCQAAIBqC06BBg+yKK66ws88+2woVKmRNmza1H3/8MWKbAwcOWJcuXaxAgQJ21llnWYsWLWzr1q0R22zYsMEaN25sOXPmdK/Ts2dPO3LkSMQ2c+bMscsuu8yyZctmpUqVslGjRp2R9wgAANKPVA1Oc+fOdaHoq6++sunTp9vhw4etYcOGtnfv3tA23bt3t0mTJtn777/vtv/999+tefPmofVHjx51oenQoUP25Zdf2ttvv+1CUb9+/ULbrF271m1Tt25dW7ZsmXXr1s06dOhgU6dOPePvGQAARK/MqfmfT5kyJeK5Ao9qjJYsWWK1a9e23bt32xtvvGFjx461evXquW3eeustK1u2rAtbV155pU2bNs1WrVplM2bMsMKFC1uVKlXs8ccft169eln//v0ta9asNmLECCtZsqQ9//zz7jX08wsWLLAXXnjBGjVqlCrvHQAARJ801cdJQUny58/vvipAqRaqQYMGoW3KlClj559/vi1cuNA919eKFSu60ORTGIqLi7OVK1eGtgl/DX8b/zXiO3jwoPv58AcAAECaCU7Hjh1zTWg1atSwChUquGVbtmxxNUZ58+aN2FYhSev8bcJDk7/eX3e8bRSI9u/fn2jfqzx58oQexYsXT+F3CwAAolGaCU7q67RixQp77733UntXrE+fPq72y39s3LgxtXcJAADEeh8nX9euXe2zzz6zefPm2XnnnRdaXqRIEdfpe9euXRG1ThpVp3X+NosWLYp4PX/UXfg28Ufi6Xnu3LktR44cCfZHI+/0AAAASDM1Tp7nudA0ceJEmzVrluvAHa5q1aqWJUsWmzlzZmiZpivQ9APVq1d3z/V1+fLltm3bttA2GqGnUFSuXLnQNuGv4W/jvwYAAECar3FS85xGzH3yySduLie/T5L6FakmSF/bt29vPXr0cB3GFYbuvfdeF3g0ok40fYEC0u23326DBw92r9G3b1/32n6tUefOne2VV16xhx56yNq1a+dC2oQJE2zy5Mmp+fYBAECUSdUap+HDh7s+RHXq1LGiRYuGHuPHjw9toykDbrjhBjfxpaYoULPbRx99FFqfKVMm18ynrwpUt912m7Vp08YGDhwY2kY1WQpJqmWqXLmym5Zg5MiRTEUAAACip8ZJTXUnkj17dhs2bJh7JKVEiRL2+eefH/d1FM6WLl2arP0EAABIU6PqAAAA0jqCEwAAQEAEJwAAgIAITgAAAAERnAAAAAIiOAEAAAREcAIAAAiI4AQAABAQwQkAACAgghMAAEBABCcAAICACE4AAAABEZwAAAACIjgBAAAERHACAAAIiOAEAAAQEMEJAADgdAend955x2rUqGHFihWz9evXu2UvvviiffLJJ8l9SQAAgPQXnIYPH249evSw66+/3nbt2mVHjx51y/PmzevCEwAAQHqUrOD08ssv23//+1975JFHLFOmTKHll19+uS1fvjwl9w8AACC6g9PatWvt0ksvTbA8W7Zstnfv3pTYLwAAgPQRnEqWLGnLli1LsHzKlClWtmzZlNgvAACANCdzcn5I/Zu6dOliBw4cMM/zbNGiRTZu3DgbNGiQjRw5MuX3EgAAIFqDU4cOHSxHjhzWt29f27dvn7Vq1cqNrhs6dKi1bNky5fcSAAAgWoOTtG7d2j0UnPbs2WOFChVK2T0DAABID8FJncOPHDliF198seXMmdM95Oeff7YsWbLYBRdckNL7CQAAEJ3B6Y477rB27dq54BTu66+/dn2c5syZk1L7BwBp0gW9J1ssW/d049TeBSB6RtUtXbrUzRoe35VXXpnoaDsAAICYDU4ZMmSwv/76K8Hy3bt3h2YRBwAASG+SFZxq167tph4ID0n6Xstq1qyZkvsHAAAQ3X2cnnnmGReeSpcubbVq1XLL5s+fb3FxcTZr1qyU3kcAAIDorXEqV66cff/993bLLbfYtm3bXLNdmzZtbPXq1VahQoWU30sAAIBonsdJE14+9dRTKbs3AAAA6TE47dq1y91qRTVOx44di1in2icAAID0JlnBadKkSW7WcM0Ynjt3bjfKzqfvCU4AACA9SlYfpwceeMBNgKngpJqnP//8M/TYuXNnyu8lAABAtAan3377ze67777QrVYAAABiQbKa6ho1amSLFy+2Cy+8MOX3CACQrnG7Gm5X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7etGOunKTGI9NMW/ki9durSVLFnSVfFv2rTJmjRpYhdddJH7MFZfsT179nDiT4SCukKnrk4PHDhgZcqUsYceesjVPI0cOdJGjRrltlPZUVvyD//vb9WqVe7kpeaSSpUquX5h48ePtxUrVrh+dn5znZpAVZ6xTGEofNDGn3/+ae3bt7cuXbq4bgmiY+yss86yefPmWfbs2e22225zNSpI6K+//nK17Cof9Uv0KTwNGDDANRlroMIvv/ySqvuZJukmv0h/fv75Z++6667zrr/+eu/RRx/1brnlFq948eJe48aNvaNHj6b27qUZK1eu9Hbs2OG+/9///udVqFDBGz16tPfSSy95+fLlc2VYuHBh77XXXqPc4undu7dXunRpr2DBgl7t2rW9Dh06eH/99Zdbt2zZMu/222/3atWq5Q0bNiy1dzVNeuqpp7wbbrjBa968ubd3796IdQsWLHB/r6VKlfKuvPJK76KLLvIOHz7sxbLnnnvOO3DggPveL4uffvrJq1y5snf55Zd7mzZtcsuOHTvmvu7Zs8c777zzvNtuuy0V9zpt++9//+udc8453kMPPeStX78+Yt2oUaO8Vq1a8bmXCIJTlPv999+9nTt3ug8JCf9wHTRokPtA8emk5n+o+F9j2aeffuqVKVPGa9u2rQua0qdPH++xxx5z38+aNcuty5Ahg3fnnXem8t6mLTq2ihQp4s2dO9cdS126dPFy5szpQsDu3bvdNt99950L6nfddRfHm+clOAEpoOvYUjBftWpVgu0VBB588EF3PPp/10eOHPFivdyefPJJ75VXXgl95ik8lShRwqtbt663ZcsWt8w/3vbv3x+TZZYUXST6AdP3wgsveOeee6738MMPexs2bEj05whPkQhOUX7F+q9//curVKmSV6dOHW/dunVu+aFDh9zXsWPHuitV/3ms/xEkdvJ+/fXXvWbNmnm5c+f2xo0b57344ovuA3j58uVu/ebNm705c+bw4Rtm9erVXs2aNb1Jkya551OnTvVy5crltWnTxitbtqyr3fRrnhRI/eON8OSFAqVO6H54V3i65557vG3btoW2SaysYr3GydepUydXZm+++WaC8FSvXr0E4Un4+/W8AQMGeDVq1PDy5MnjdezY0fv8889D64YMGeJq5/r27ev9+uuvqbqf0YDgFKUeeeQRr1ChQt6YMWO8KVOmeFWr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", "text/plain": [ "
" ] @@ -620,25 +595,47 @@ } ], "source": [ - "# Model-based \n", - "plt.figure(figsize=(6,4))\n", - "plt.bar(range(len(feat_order)), imp_model_sorted)\n", - "plt.xticks(range(len(feat_order)), feat_order, rotation=45, ha=\"right\")\n", - "plt.ylabel(\"Importance\")\n", - "plt.title(\"Feature Importance (Model-based)\")\n", - "plt.tight_layout()\n", - "plt.show()" + "imp_model = fi.model_importance(plot=True)" + ] + }, + { + "cell_type": "markdown", + "id": "f68d3f1a", + "metadata": {}, + "source": [ + "**Permutation-based importance** measures how much test performance drops when we randomly shuffle one feature at a time (breaking its relationship to the target). The bar height is the mean drop across repeats; the error bars show variability across shuffles." ] }, { "cell_type": "code", - "execution_count": null, - "id": "a4cc5e5d", + "execution_count": 21, + "id": "a449662d", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[LightGBM] [Info] Auto-choosing col-wise multi-threading, the overhead of testing was 0.000316 seconds.\n", + "You can set `force_col_wise=true` to remove the overhead.\n", + "[LightGBM] [Info] Total Bins 1530\n", + "[LightGBM] [Info] Number of data points in the train set: 9234, number of used features: 6\n", + "[LightGBM] [Info] Start training from score 82.456995\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\sin22002\\Dropbox\\Git Management\\modular-ml\\.venv\\Lib\\site-packages\\sklearn\\utils\\validation.py:2749: UserWarning: X does not have valid feature names, but LGBMRegressor was fitted with feature names\n", + " warnings.warn(\n", + "c:\\Users\\sin22002\\Dropbox\\Git Management\\modular-ml\\.venv\\Lib\\site-packages\\sklearn\\utils\\validation.py:2749: UserWarning: X does not have valid feature names, but LGBMRegressor was fitted with feature names\n", + " warnings.warn(\n" + ] + }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAGGCAYAAACNCg6xAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAARGpJREFUeJzt3QncVOP///FP+yLtq0Qh0k5ZWhRZQiRbWSsqIZQSJbSQElKSQuirSETiK5H2FClFRb6WVGjVvlPn/3hfv/8ZM3Pfd52pe+77nntez8fj1MyZc89cc811zvmcazs5PM/zDAAAAIeV8/CbAAAAQAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAJJ01a9ZY/vz57YsvvsjspCSs0aNHW44cOey3337L7KRkW99//73lzp3bli1bltlJQRgCJ8TlYJra0qNHj7h85rx586xPnz62detWy6r5sXDhQktUL774ovse2Um/fv3snHPOsQYNGoTWtW3bNqK8Fi5c2GrVqmXPPvus7du3zxLR5MmT3b5xNJ588kn74IMPLJlEl4W0Fm2XHt566y0bMmRIivVVq1a1Zs2a2WOPPZYun4P0kTud3gdIcWKqVKlSxLrq1avHLXDq27evO4gVLVo0Lp+RzBQ4lSxZMt1OEplt48aN9p///Mct0fLly2ejRo1yjxWIv/fee/bAAw/Y119/bW+//bYlYuA0fPjwowqeFDhdd9111qJFi4j1t956q91www0uz7Kbjh072kUXXRR6vnLlShe83HHHHXbeeeeF1p988snpFjipVqlLly4pXrvzzjvt8ssvt19++SXdPg9Hh8AJcXHZZZdZ3bp1LZHt2rXLjjnmGEtWu3fvtoIFC1p2M3bsWNf8ceWVV6Z4TetvueWW0PO7777b1UyNHz/eBg8ebMcdd9wRf+7Bgwdt//79rokwO8iVK5dbsqN69eq5xacaYwVOWhdePjKCArhixYq5QF8XpMh8NNUhU3zyySfuyk2BybHHHuuqo5cvXx6xzXfffedqOU466SR3silbtqzdfvvt9tdff4W20ZV09+7d3WPVcPlV6Op3oUWPU2tm0vrwq3A91jr1Kbjpppvcgaphw4YRJ9s6depYgQIFrHjx4u5KW/1kjoS+U6FChWz16tV2xRVXuMfly5d3NQOydOlSa9KkicubE0880V2Nptb8N3v2bHdlXKJECdes1Lp1a9uyZUuqNUbVqlVzNQM68Xfq1ClFs+b555/vagQXLVpkjRo1cgHTww8/bBUrVnS/y6xZs0J5q21l8+bNrjamRo0a7jsoDQqYv/3224j3njlzpvu7d955x/r372/HH3+8+z0vvPBC+/nnn1Ok96uvvnJX2PoNlAc1a9a0oUOHRmyzYsUKVwui30LvpSD9ww8/DJT/anZSMKQ0H07OnDlD39fvy6Nmu969e9spp5zi8rRChQr24IMPpmjO03e+55577M033wzl/5QpU0K/39y5c+2+++6zUqVKuZpS/ZYKrPTb6LfU99ei9/Y8L0V+6v9w0eVd5cwvU+HNS75nnnnG6tev78qPyrXK94QJE1J8B11A6KQd3TyVVh+nWMqb9rcLLrjAlTftA4MGDbIg/vnnH3v88cddDYw+R+VU5TX6N9B67WPK67PPPtuVFR1P3njjDUsPKquXXnqpFSlSxH2Hxo0bp+g3t2PHDleTpLQoraVLl7aLL77Yvvnmm1BefPzxx7Zq1apQHmtbX548edw2kyZNSpc04+hR44S42LZtm23atClinZp7ZMyYMdamTRtr2rSpPfXUU65mY8SIES5QWbx4ceigMXXqVPv111/ttttuc0GTTuAvv/yy+//LL790B5hrrrnG/ve//9m4cePsueeeC32GTkZqkonV9ddfb5UrV3bNE/7JSif7Rx991Fq2bGnt27d37zts2DAXYCi9R9I8eODAARdk6D10stDJVSdZBQq9evWym2++2X23kSNHupOornSjmz61vT5bQd+PP/7o8lAHX//EKnpNzZi6ar3rrrtC26npSQd4HZR9CkiVJgWFuqouU6aMO2Dfe++9LshQukTrRb+NghDlmdK2fv16e+mll9zJQyfE6NqZgQMHukBEwZbKh763vqdOPj795jrRlStXzjp37ux+9x9++MH++9//uuei3199k3SiVb855ZmCMjUlqWnt6quvTjPf//77b/fdlRdBqYlEFGCo1qh58+buRKxmm9NPP90Fuip7KofRfYGmT5/u0qbfSmVTZXvJkiXuNeWrvp9+H5VnlW39nmp6PuGEE1wZVFPb008/7YIMlYNYKBD7888/XZ5qn4umYFTfRb+BAjY1Req3VF7rQkb0dyrzCjr0feVQzUWxlDcF+Qo6VM61byloe+ihh1wgrnJ4KEqTgjkFz926dXNlaMCAAa6sTJw4MWJbBefarl27du6489prr7ngT4GiArwjpd9W6dT7KJBW2X799dfdRc+cOXNcnvlNbfpuKgPqs6T9TOVHaT3zzDPdfqX94ffff3flSKKDen2GAqft27e7CxRkMg9IR6+//rqijVQX2bFjh1e0aFGvQ4cOEX+3bt06r0iRIhHrd+/eneL9x40b595r9uzZoXVPP/20W7dy5cqIbfVc65WmaFrfu3fv0HM91robb7wxYrvffvvNy5Url9e/f/+I9UuXLvVy586dYn1a+fH111+H1rVp08ate/LJJ0PrtmzZ4hUoUMDLkSOH9/bbb4fWr1ixIkVa/fesU6eOt3///tD6QYMGufWTJk1yzzds2ODlzZvXu+SSS7wDBw6EtnvhhRfcdq+99lpoXePGjd26kSNHpvgO1apVc69H27t3b8T7+nmeL18+r1+/fqF1M2bMcO99+umne/v27QutHzp0qFuvvJR//vnHq1SpknfiiSe6/Ah38ODB0OMLL7zQq1Gjhvv88Nfr16/vVa5c2TuUn3/+2X3msGHDUrym3+WYY47xNm7c6BZtq99Iv0nNmjXdNmPGjPFy5szpzZkzJ+JvlW963y+++CK0Ts+17fLlyyO29X+/pk2bRnyvevXquc+68847Q+uUJ8cff3xE/vv5qf8PV947deoU2veiRe9fKkvVq1f3mjRpErFeeaK8ieZ/D3+/O5Ly9sYbb4TWqWyULVvWu/baa71DWbJkifvb9u3bR6x/4IEH3Prp06eH1qksRR8vlE6V0W7dunlBaf8Nz1v9bipr0b+h8lRl+OKLLw6t03FNv8OhNGvWzKU1LW+99Zb7/K+++ipwmhE/NNUhLtREoCvd8EX0v6rtb7zxRlcj5S/qK6HmkxkzZoTeQ80Hvr1797rtzj33XPfcr+ZOb7o6DPf++++7WgZdEYenVzUFqpkKT2+sdNXsU03Daaed5mpP9Fk+rdNrqt2JphqA8Ct4XeGrj45qKeTzzz93NQlqJtDVsK9Dhw7uqlXNA+HUjKDavaC0vf++qkHTlbSulJXm1H4fvXfevHlDz/1Otv53U+2dOuEqvdG1eH4NmpoHdaWvPFITiP976LNVg/nTTz/ZH3/8kWaa/WZeNYGlRs1Sqq3UoqY4Nf+ots+vxXj33XddLVOVKlUiyoNqGSS6PKj2TbUMqVENSHjTmcq/4i2t92m/UDNkar//0Qrfv1T7o1oP/SZHum/FWt5UVsL7C6lsqJbmcN/VL99du3aNWK+aJ4n+HOV/eIdu/bYqo0eTp6o1VFlTs77KlF8OVH7UBK1mdB03RGVZNWKq/TtSfnmNrsVH5qCpDnGhA2BqncN1sBH/RBMtvBpaJ0lV+6sJYcOGDRHb6SAfD9HNYUqvTmYKklITHrjEQn0tdAAPp34S6v8TfjL116fWdyk6TToRqYnL73OiZjvRSSKcTlDq5+G/7lPTV3hgczg6Mai5R31aFPAoePKpWSuamp9SOxn4381vEjvU6Es1u+j3UNOpltSorOi7HEp4n6Ho3+Wjjz4KBYYqD/pNwsuDmliif7vwzz5UeTpUfuh3FvWZCvL7Hy01yT3xxBMuCAjvGxRd/oKKtbylVtZVJtS38XCfo8BMgW04XcwoSIn+nOh89j/naPLUP46p6S8tOkbpc9Qkre30u6rJTf331OyqPAnKL69H+tsgfRE4IUP5V2HqO6EDXTTVmPhUq6D+Hur8Xbt2bRcY6O/VL8J/n0NJ6yATfoI/1FW4n169jzqzpzaCKEgH49SkNRoprfVpnejTU/R3Pxz1wVHwog776qirjto6oanGIbXfJz2+m/++6ielGqbURJ9Qw/kBXVonTaUxfBh6ap+vPjgaYZea6KDnUHkaSxkIz6MjKdfR1AdH/ZvUx06BrwJuXQSoj070YIR4OdryEDSIiMc+5ZdD9T/TsSk1/rFBxzHVeKnW8rPPPnN/o76dqs0+XF8un19e/T6cyFwETshQfsdSjSw51AlKB4pp06a5Gqfwyd/8K70gB1C/RiN6RE/0Fenh0qsDrGoOTj31VMtKlBcakeTbuXOnrV271l3RikbkiTrohl/dqjlFNUSHyv8g+asOr/r8V199NWK98vtIDvB+2dB8Nmmlzf8eOskHTX907YOCGX3/I6E0atSgmmMy6+o/lnKdVhrViV61a59++mnEPEwKnIK+R7T0Km9BPkeBi8q/mk19GpygPPHTEU9+WVUNeZDvpcBUU1toUa2kOoVr0IkfOB0uj5V/uijJasegZEUfJ2Qo1RLoYKPaCo1wiuaPhPOvEqOvClObXdefayn6RKLP0Qlc/Q3C6Qo7KI34UVoUwEWnRc/Dp0bIaBqFFZ6HGr2kYdr+wVgHdDWTPP/88xFpV6CjZgR/5NThKH9Tm5Vd+RKdJ+oDdKg+Roeik4kCVP3G0Z/nf44Cbo300+g9BYnRDjeSUgGXmpCPdCZ31R7o+73yyispXtuzZ4/r4xJvCgyU90HKdVr7hv5eJ+vwWio18aY2Q3hav3+09Cpvh+NfGEQfC/xawPT6nENRk5uCJ03poAuWtMqh8je6W4HKsEachjePKo8P1f1A04RoBKDfnIvMRY0TMpSCGZ3gNeuwTpQa+q7+IprTSJ06Ncz8hRdecNv5Q/UVHKjPiqq5U6sp0EFMNKxX76eToyY31MFIHbA1DF7/64Spk42GjQelg6P6gfTs2dOdWDTkXfNOKR2qelcHbTUbZQZdyavmQydzXeXrxKkpHdQEI8pXpVtBn5o3td7f7qyzzgo8kZ/yV7+Z8kHNYDrwq4+apg3QhHzq9K35gDQsX9MqxNJ3I5yuqPU5+u3U/KH31ZW65mzSFASqHfEHHuh7qslMHY/1eaptmD9/vhvSHT2PVLSrrrrKlZUjGdqtcqvpBTSIQB3BVV51clQatV5pjPfErzp5atoATYmh4EdlVP2VovtXhe8bmi9KFy0KmLSPKLhQoKFyoQ7O+lvlq37f6D5Geg91/PYnAFVwq47s0dKrvB2OboOjPkO6cFBApw74CxYscNMTaP8Mr4WNF5VVzTCvixQFNCqrOkYpqFa5ULlSXzkNYFBfLk2HoHSr+U55qekZdCuf8DzWJKvq8K680nb+BK06/mkeNdVWIYuI44g9JKHUht+nRkOpNZRXQ3Xz58/vnXzyyV7btm29hQsXhrb5/fffvauvvtpNX6Dtrr/+eu/PP/9MMTxfHn/8ca98+fJu+Hf4EGkND27Xrp37+2OPPdZr2bKlG46c1nQEGoaemvfee89r2LChG5qtpUqVKm6I8Y8//hhzfvjD3qNpiLaG/kfTMGUNV45+z1mzZnl33HGHV6xYMa9QoULezTff7P31118p/l7DwZXePHnyeGXKlPHuuuuuFMP90/psf6oIfb7yT5/rD43XdAAa0l2uXDk3lUKDBg28+fPnu9dTGz7/7rvvBpouYu7cuW44tz5P+aSpAKKnD/jll1+81q1bu+Hr+l767a+44gpvwoQJ3uGsX7/eTSWhqQXCpfW7RNOw/aeeesrll4a1K/81NUTfvn29bdu2hbbTd0ttGHpa+0haZTC1dGkbDdsvWLCg+/yOHTt6y5YtS5Gfms7g3nvv9UqVKuWmOgg/5L/66qtuSL2+g8qH/s5PQzhNidGoUSP3G+s1f2qC6OkI0qO86b0PNSzf9/fff7v81tB/fU6FChW8nj17RkxRkdq+E/75qU2xEXQ6At/ixYu9a665xitRooTLR32ejjHTpk0LTbHQvXt3r1atWqHyrMcvvvhixPvs3LnTu+mmm9yxTp8TngeffPKJW/fTTz8FTi/iK4f+yezgDUBwmrFZV7i6ak3029pkFg35V82jOkkDWZlq0VSzGD2xJzIPTXUAko5melZHW81mreY2ICvyZ833Z5tH1kDgBCDpaHSdJlUFsjKNGtSAD2QtjKoDAAAIiD5OAAAAAVHjBAAAEBCBEwAAQEBJ1zlcU/XrLtWaxJAbJgIAAM/z3ISlmuRVE5weStIFTgqaom/ECQAAsGbNGjfb+6EkXeCkmiY/c2K93QIAAMh+dAsmVar4McKhJF3g5DfPKWgicAIAAL4gXXjoHA4AABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEBJd8uV7GTt2rVuCapcuXJuAQAAR4bAKYG99NJL1rdv38Db9+7d2/r06RPXNAEAkJ0ROCWwjh07WvPmzUPP9+zZYw0bNnSP586dawUKFIjYntomAACODoFTAotuetu1a1foce3ate2YY47JpJQBAJA90TkcAAAgIAInAACAgAicAAAAAqKPUxxU7PFxpnzuwf17Q49Pf3SK5cyb3zLLbwObZdpnAwAQL9Q4AQAABETgBAAAEBCBEwAAQEAETgAAAAHROTyB/bNzsx3YuTn03Pt7f+jx/vW/Wo48eSO2z1WouOUuVDxD0wgAQHZC4JTAdi75xLZ9MS7V19a/9WCKdUUa3GhFG96cASkDACB7InBKYIVqX2YFTjkn8PaqcQIAAEeOwCmBqdmNpjcAADIOncMBAAACInACAAAIiMAJAAAgIAInAACARAicBgwYYGeddZYde+yxVrp0aWvRooX9+OOPh/27d99916pUqWL58+e3GjVq2OTJkzMkvQAAILllauA0a9Ys69Spk3355Zc2depU+/vvv+2SSy6xXbt2pfk38+bNsxtvvNHatWtnixcvdsGWlmXLlmVo2gEAQPLJ4XmeZ1nExo0bXc2TAqpGjRqluk2rVq1cYPXf//43tO7cc8+12rVr28iRIw/7Gdu3b7ciRYrYtm3brHDhwhYPFXt8bMnut4HNMjsJAAAEEktskKX6OCnBUrx42nMTzZ8/3y666KKIdU2bNnXrU7Nv3z6XIeELAADAkcgygdPBgwetS5cu1qBBA6tevXqa261bt87KlCkTsU7PtT6tflSKIv2lQoUK6Z52AACQHLJM4KS+Tuqn9Pbbb6fr+/bs2dPVZPnLmjVr0vX9AQBA8sgSt1y55557XJ+l2bNn2/HHH3/IbcuWLWvr16+PWKfnWp+afPnyuQUAACCha5zUL11B08SJE2369OlWqVKlw/5NvXr1bNq0aRHrNCJP6wEAALJtjZOa59566y2bNGmSm8vJ76ekvkgFChRwj1u3bm3ly5d3fZWkc+fO1rhxY3v22WetWbNmrmlv4cKF9vLLL2fmVwEAAEkgU2ucRowY4fodnX/++VauXLnQMn78+NA2q1evtrVr14ae169f3wVbCpRq1aplEyZMsA8++OCQHcoBAAASvsYpyBRSM2fOTLHu+uuvdwsAAEBSjqoDAADI6gicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAADIiMBp37596ZcSAACA7BQ4ffLJJ9amTRs76aSTLE+ePFawYEErXLiwNW7c2Pr3729//vln/FIKAACQCIHTxIkT7dRTT7Xbb7/dcufObQ899JC9//779umnn9qoUaNc4PT555+7gOrOO++0jRs3xj/lAAAAGSx3kI0GDRpkzz33nF122WWWM2fKWKtly5bu/z/++MOGDRtmY8eOtfvvvz/9UwsAAJDVA6f58+cHerPy5cvbwIEDjzZNAAAAWRKj6gAAANKzxincgQMHbPTo0TZt2jTbsGGDHTx4MOL16dOnx/qWAAAA2TNw6ty5swucmjVrZtWrV7ccOXLEJ2UAAACJHji9/fbb9s4779jll18enxQBAABklz5OefPmtVNOOSU+qQEAAMhOgVO3bt1s6NCh5nlefFIEAACQXZrq5s6dazNmzHCziFerVs3NIB5OE2MCAABkRzEHTkWLFrWrr746PqkBAADIToHT66+/Hp+UAAAAZHFMgAkAABCvGieZMGGCm5Jg9erVtn///ojXvvnmmyN5SwAAgOxX4/T888/bbbfdZmXKlLHFixfb2WefbSVKlLBff/3V3QQYAAAgu4o5cHrxxRft5ZdftmHDhrk5nR588EGbOnWq3XfffbZt27aY3mv27Nl25ZVX2nHHHedmIP/ggw8Ouf3MmTPddtHLunXrYv0aAAAA8Q+c1DxXv35997hAgQK2Y8cO9/jWW2+1cePGxfReu3btslq1atnw4cNj+rsff/zR1q5dG1pKly4d098DAABkSB+nsmXL2ubNm+3EE0+0E044wb788ksX/KxcuTLmSTHVtHckzXsKlDQtAgAAQJaucWrSpIl9+OGH7rH6Ot1///128cUXW6tWrTJsfqfatWtbuXLl3Od+8cUXh9x23759tn379ogFAAAgQ2qc1L/p4MGD7nGnTp1cx/B58+ZZ8+bNrWPHjhZPCpZGjhxpdevWdQHRqFGj7Pzzz7evvvrKzjzzzFT/ZsCAAda3b9+4pgsAACSHHF4WuemcOnlPnDjRWrRoEdPfNW7c2DUZjhkzJtXXFWBp8anGqUKFCq4je+HChS0eKvb42JLdbwObZXYSAAAIRLFBkSJFAsUGRzQB5pw5c+yWW26xevXq2R9//OHWKXDRfewymqZD+Pnnn9N8PV++fC4TwhcAAIAjEXPg9N5771nTpk3diDrN4+TX5ihKe/LJJy2jLVmyxDXhAQAAZLnA6YknnnD9jF555RXLkydPaH2DBg1injV8586dLvDRIhqZp8ea8kB69uxprVu3Dm0/ZMgQmzRpkqthWrZsmXXp0sWmT5/u+loBAABkuc7hmkOpUaNGKdarbXDr1q0xvdfChQvtggsuCD3v2rWr+79NmzY2evRoN0eTH0SJbu/SrVs31zxYsGBBq1mzpn3++ecR7wEAAJCl5nFSjU/FihUj1qt/00knnRTTe2lE3KH6pit4CqdZyrUAAAAkRFNdhw4drHPnzm4KAI2E+/PPP+3NN9+0Bx54wO666674pBIAACARa5x69Ojh5nG68MILbffu3a7ZTiPXFDjde++98UklAABAIgZOqmXq1auXde/e3TXZqYN31apVrVChQvFJIQAAQKIGTr68efO6gAkAACBZxBw47d2714YNG2YzZsywDRs2hG6/4ot1SgIAAIBsGzi1a9fOPvvsM7vuuuvcrN1qugMAAEgGMQdO//3vf23y5MluwksAAIBkEvN0BOXLl7djjz02PqkBAADIToHTs88+aw899JCtWrUqPikCAADILk11devWdR3ENUu4bnsSfr862bx5c3qmDwAAIHEDpxtvvNHdK+7JJ5+0MmXK0DkcAAAkjZgDp3nz5tn8+fOtVq1a8UkRAABAdunjVKVKFduzZ098UgMAAJCdAqeBAwdat27dbObMmfbXX3/Z9u3bIxYAAIDsKuamuksvvdT9r5v8hvM8z/V3OnDgQPqlDgAAIJEDJ91qBQAAIBnFHDg1btw4PikBAADIDn2cVq9eHdObaroCAACApAyczjrrLOvYsaN9/fXXaW6zbds2e+WVV6x69er23nvvpWcaAQAAEqep7vvvv7f+/fvbxRdfbPnz57c6derYcccd5x5v2bLFvb58+XI788wzbdCgQXb55ZfHP+UAAABZscapRIkSNnjwYFu7dq298MILVrlyZdu0aZP99NNP7vWbb77ZFi1a5CbGJGgCAADZVUydwwsUKGDXXXedWwAAAJJNzBNgAgAAJCsCJwAAgIAInAAAAAIicAIAAAiIwAkAACCegdOYMWOsQYMGbi6nVatWuXVDhgyxSZMmHcnbAQAAZM/AacSIEda1a1c3X9PWrVvtwIEDbn3RokVd8AQAAJBdxRw4DRs2zN1apVevXpYrV67Q+rp169rSpUvTO30AAACJGzitXLnSzjjjjBTr8+XLZ7t27UqvdAEAACR+4FSpUiVbsmRJivVTpkyx008/Pb3SBQAAkNi3XBH1b+rUqZPt3bvXPM+zBQsW2Lhx42zAgAE2atSo+KQSAAAgEQOn9u3bu3vWPfLII7Z792676aab3Oi6oUOH2g033BCfVAIAACRi4CQ333yzWxQ47dy500qXLp3+KQMAAEj0wEmdw//55x+rXLmyFSxY0C3y008/WZ48eaxixYrxSCcAAEDidQ5v27atzZs3L8X6r776yr0GAACQXcUcOC1evNjNGh7t3HPPTXW0HQAAQNIGTjly5LAdO3akWL9t27bQLOIAAADZUcyBU6NGjdzUA+FBkh5rXcOGDdM7fQAAAInbOfypp55ywdNpp51m5513nls3Z84c2759u02fPj0eaQQAAEjMGqeqVavad999Zy1btrQNGza4ZrvWrVvbihUrrHr16vFJJQAAQKLO46QJL5988sn0Tw0AAEB2C5y2bt3qbrWiGqeDBw9GvKbaJwAAgOwo5sDpo48+crOGa8bwwoULu1F2Pj0mcAIAANlVzH2cunXrZrfffrsLnFTztGXLltCyefPm+KQSAAAgEQOnP/74w+67777QrVYAAACSRcyBU9OmTW3hwoXxSQ0AAEB26uPUrFkz6969u33//fdWo0YNd2PfcM2bN0/P9AEAACRu4NShQwf3f79+/VK8ps7h3HYFAABkVzEHTtHTDwAAACSLmPs4AQAAJKsjmgBz165dNmvWLFu9erXt378/4jWNuAtq9uzZ9vTTT9uiRYts7dq1NnHiRGvRosUh/2bmzJnWtWtXW758uVWoUMEeeeQRa9u27ZF8DQAAgPgGTosXL7bLL7/cdu/e7QKo4sWL26ZNm9z0BKVLl44pcNLf16pVy80Ldc011xx2+5UrV7rO6Xfeeae9+eabNm3aNGvfvr2VK1fOjfYDAADIUoHT/fffb1deeaWNHDnSihQpYl9++aUbWXfLLbdY586dY3qvyy67zC1B6TMrVapkzz77rHt++umn29y5c+25554jcAIAAFmvj9OSJUvc7OE5c+a0XLly2b59+1yT2aBBg+zhhx+2eJo/f75ddNFFEesUMGl9WpS+7du3RywAAAAZEjipdklBk6hpTv2cRLVPa9assXhat26dlSlTJmKdnisY2rNnT6p/M2DAAJc2f1GQBwAAkCGB0xlnnGFff/21e9y4cWN77LHHXH+jLl26WPXq1S2r6dmzp23bti20xDu4AwAA2VfMgdOTTz7pOmNL//79rVixYnbXXXfZxo0b7aWXXrJ4Klu2rK1fvz5inZ4XLlzYChQokOrf5MuXz70evgAAAGRI5/C6deuGHqupbsqUKZZR6tWrZ5MnT45YN3XqVLceAAAgy9U4NWnSxLZu3ZpivfoZ6bVY7Ny503U21+JPN6DHfr8pNbO1bt06tL2mIfj111/twQcftBUrVtiLL75o77zzjhvpBwAAkOUCJ01AGT3ppezdu9fmzJkT03stXLjQ9ZnSIprYUo/Vb0o0KaYfRImmIvj4449dLZPmf9K0BKNGjWIqAgAAkLWa6r777rvQ4++//96NcPPpxr5qsitfvnxMH37++eeb53lpvj569OhU/0aTcAIAAGTZwKl27dqWI0cOt6TWJKfO2cOGDUvv9AEAACRe4KT+R6odOumkk2zBggVWqlSp0Gt58+Z1HcU1ISYAAIAle+B04okn2t9//21t2rSxEiVKuOcAAADJJGess4ZPnDgxfqkBAADITqPqrrrqKvvggw/ikxoAAIDsNAFm5cqVrV+/fvbFF19YnTp17Jhjjol4/b777kvP9AEAACRu4PTqq69a0aJFbdGiRW4JpxF3BE4AACC7ijlw0ug6AACAZBRzH6dwmp7gUBNYAgAAWLIHTm+88YbVqFHDTXqppWbNmjZmzJj0Tx0AAEAiN9UNHjzYHn30UbvnnnusQYMGbt3cuXPdDXg3bdrEDXcBAEC2FXPgpNuqjBgxwlq3bh1a17x5c6tWrZr16dOHwAkAAGRbMTfVrV271urXr59ivdbpNQAAgOwq5sDplFNOsXfeeSfF+vHjx7s5ngAAALKrmJvq+vbta61atbLZs2eH+jhpMsxp06alGlABAAAkbY3Ttddea1999ZWVLFnS3XpFix4vWLDArr766vikEgAAIBFrnES3Whk7dmz6pwYAACC7BU4HDhywiRMn2g8//OCeV61a1d38N3fuI3o7AACAhBBzpLN8+XI3/cC6devstNNOc+ueeuopK1WqlH300UdWvXr1eKQTAAAg8fo4tW/f3s3Z9Pvvv9s333zjljVr1rjZw++44474pBIAACALiLnGacmSJbZw4UIrVqxYaJ0e9+/f384666z0Th8AAEDi1jideuqptn79+hTrN2zY4OZ4AgAAyK5iDpwGDBhg9913n02YMME112nR4y5duri+Ttu3bw8tAAAASd1Ud8UVV7j/W7ZsaTly5HCPPc9z/1955ZWh53pNo+8AAACSNnCaMWNGfFICAACQ3QKnxo0bxyclAAAAWdwRzVi5d+9e++6771yH8IMHD0a8pjmeAAAAsqOYA6cpU6ZY69atbdOmTSleo18TAADIzmIeVXfvvffa9ddfb2vXrnW1TeELQRMAAMjOYg6cNIdT165drUyZMvFJEQAAQHYJnK677jqbOXNmfFIDAACQnfo4vfDCC66pbs6cOVajRg3LkydPxOuaHBMAACA7ijlwGjdunH322WeWP39+V/PkT4IpekzgBAAAsquYA6devXpZ3759rUePHpYzZ8wtfQAAAAkr5shn//791qpVK4ImAACQdGKOftq0aWPjx4+PT2oAAACyU1Od5moaNGiQffrpp1azZs0UncMHDx6cnukDAABI3MBp6dKldsYZZ7jHy5Yti3gtvKM4AACAJXvgNGPGjPikBAAAIIujhzcAAEB61zhdc801gbZ7//33g74lAABA9gycihQpEt+UAAAAZJfA6fXXX49vSgAAALI4+jgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAACRS4DR8+HCrWLGi5c+f38455xxbsGBBmtuOHj3acuTIEbHo7wAAALJ94DR+/Hjr2rWr9e7d27755hurVauWNW3a1DZs2JDm3xQuXNjWrl0bWlatWpWhaQYAAMkp0wOnwYMHW4cOHey2226zqlWr2siRI61gwYL22muvpfk3qmUqW7ZsaClTpkyGphkAACSnTA2c9u/fb4sWLbKLLrro3wTlzOmez58/P82/27lzp5144olWoUIFu+qqq2z58uUZlGIAAJDMMjVw2rRpkx04cCBFjZGer1u3LtW/Oe2001xt1KRJk2zs2LF28OBBq1+/vv3++++pbr9v3z7bvn17xAIAAJCQTXWxqlevnrVu3dpq165tjRs3tvfff99KlSplL730UqrbDxgwwIoUKRJaVEsFAACQcIFTyZIlLVeuXLZ+/fqI9XquvktB5MmTx8444wz7+eefU329Z8+etm3bttCyZs2adEk7AABIPpkaOOXNm9fq1Klj06ZNC61T05ueq2YpCDX1LV261MqVK5fq6/ny5XOj8MIXAACAI5HbMpmmImjTpo3VrVvXzj77bBsyZIjt2rXLjbITNcuVL1/eNblJv3797Nxzz7VTTjnFtm7dak8//bSbjqB9+/aZ/E0AAEB2l+mBU6tWrWzjxo322GOPuQ7h6rs0ZcqUUIfx1atXu5F2vi1btrjpC7RtsWLFXI3VvHnz3FQGAAAA8ZTD8zzPkohG1amTuPo7xavZrmKPjy3Z/TawWWYnAQCAdI8NEm5UHQAAQGYhcAIAAAiIwAkAACAgAicAAICACJwAAAACInACAABIlHmcgMy2du1atwSlWerTmqkeAJC9ETgh6ekG0X379g28fe/eva1Pnz5xTRMAIGsicEKWlJGTiO5bX8JKXNEt9Nz752/bPOV597j4pfdZjtx5IrZ/aVUJG50B6WMSUQDIegickPT2/DTftn0xLtXX/AAqXJEGN1q+MidlQMoAAFkNgROSXqHal1mBU84JvH2uQsXjmh4AQNZF4ISkl7tQcbcAAHA4TEcAAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETAABAQAROAAAAARE4AQAABETgBAAAEBCBEwAAQEAETgAAAAEROAEAAASUO+iGAJCWtWvXuiWocuXKuQUAEg2BE4Cj9swzz9jgwYMDb9+1a1d79tln45omAIgHAicgm6rY4+MM+6zNc36NaftX5vxq72VQ+n4b2CxDPgdAciBwAnDUCp99jR1T9fzA2+cqVDyu6QGAeCFwAnDUchcq7hYAyO4YVQcAABAQgRMAAEBABE4AAACJFDgNHz7cKlasaPnz57dzzjnHFixYcMjt3333XatSpYrbvkaNGjZ58uQMSysAAEhemR44jR8/3s3p0rt3b/vmm2+sVq1a1rRpU9uwYUOq28+bN89uvPFGa9eunS1evNhatGjhlmXLlmV42gEAQHLJ9FF1mjSvQ4cOdtttt7nnI0eOtI8//thee+0169GjR4rthw4dapdeeql1797dPX/88cdt6tSp9sILL7i/BYBEtGTJElu+fHng7atVq2a1a9eOa5oSEfmIbB047d+/3xYtWmQ9e/YMrcuZM6dddNFFNn/+/FT/RutVQxVONVQffPBB3NMLIPlk1ESi697qYfvWBK85z1ehupW9aaAlwiSiGTkZa1bNx0SaiJXgMwsHTps2bbIDBw5YmTJlItbr+YoVK1L9m3Xr1qW6vdanZt++fW7xbdu2zf2/fft2i5eD+3Zbsjva/CUPycNky8eijVrb33+tCbx9nhIVMixtiZKHWTkfjzYPq/f+1DLK+nd72/4/fgi8fd7yp1uZ6/tavC3r2zTuv4/neVm/qS7eBgwYYH37pvxBK1SokCnpSRZFhmR2ChIfeZg+yMejRx4eveych/v/+MHWDGmZLfJwx44dVqRIkawbOJUsWdJy5cpl69evj1iv52XLlk31b7Q+lu3VDBjetHfw4EHbvHmzlShRwnLkyGHZjaJmBYVr1qyxwoULZ3ZyEhb5ePTIw6NHHqYP8vHoZfc89DzPBU3HHXfcYbfN1MApb968VqdOHZs2bZobGecHNnp+zz33pPo39erVc6936dIltE6dw7U+Nfny5XNLuKJFi1p2p4KdHQt3RiMfjx55ePTIw/RBPh69wtk4Dw9X05RlmupUG9SmTRurW7eunX322TZkyBDbtWtXaJRd69atrXz58q7JTTp37myNGze2Z5991po1a2Zvv/22LVy40F5++eVM/iYAACC7y/TAqVWrVrZx40Z77LHHXAdv9cyfMmVKqAP46tWr3Ug7X/369e2tt96yRx55xB5++GGrXLmyG1FXvXr1TPwWAAAgGWR64CRqlkuraW7mzJkp1l1//fVuQUpqltRkotHNk4gN+Xj0yMOjRx6mD/Lx6JGH/8rhBRl7BwAAgMy/5QoAAECiIHACAAAIiMAJAAAgIAInAACAgAicEpQmCgUAABmLwCnBvPHGG25q+PC5rXBkGFAaOwL29EV+AomHs28CeeaZZ+zOO++0b7/9NrOTktC++OIL9392vFdhvPkB+yeffJLZSUlIs2bNCj3u16+fDR06NFPTg+SVWtDOxWQwBE4JYv78+fbbb7/ZxIkT3ezqODK6Rc9dd92V2clIaH/88Ye73dHw4cMzOykJZcOGDXbttdda06ZN3b02Bw0a5B7jyLz//vvu1lvTp0+3bdu2ZXZyEi5o8i+Cfv31V/vf//7nHnMxGQyBUwL46KOPrGPHjvbxxx/b8ccf79ZRxX9kdCufP//809avX8/VVUAHDhyIeO7fO3LcuHG2aNGiTEtXoildurTNmTPHXQTp3prz5s2zqlWr2j///JPZSUs4PXv2tLZt29rYsWNd8Pnoo4/a0qVLMztZCcMPmpSPF1xwgTVq1MguueQSW7VqVWYnLSEQOCWAE044wapVq+bu5Td58uRQwSd4il3FihXdVdX27dvd/9FBAVLKlSuX+3/ChAnuBtxy1VVXWZ48eeyzzz5zzymLaQvPGwVNKnfHHnusu9emgvfcuXOnyD+C+rQpWP/mm2/s008/tcWLF7vgaerUqfb888/bd999l9nJy9LCj3fvvPOOq4FXrd2IESPcxeQVV1xBHibKvepwaLVq1XL3CNIJTFf5JUuWtNtuuy0UPNFR/NB0QP3666/dDaLLlSvnap10AtMNov2gIPyERXV1SjpJtWzZ0po0aeLuE6mbc999993uql9BlGpOKIsphQ/keOihh2z58uWu1kl5pZPUZZdd5m5qHp5vOrlFl0v8H53g586da8WKFbOzzjrLrVNZlD59+rh9995777UaNWpkckqzln379rl7zPnl6r333rO//vrLlcnrrrvOrbv44outcePGdtNNN7nzDHmYNo5yWZRO9DpZKfrfu3evValSxR588EFX8zRq1CgbPXq0204HXK5O07Z582bXhr9p0yZ3MOjcubP99NNP1qNHD7vwwgvtkUcecSMVdeUlBE3/J7oG5LTTTrNKlSq5qvzff//drrzySjv55JPdQVd9xnbu3EnQlAq/PH3//ffuhK+mkZo1a7p+iuPHj7dly5a5/mJ+c52a5LV/I3U7duxwNZ+qcVKfT5+Cp759+7rmT3W6/+WXXzI1nVmJgqHwwRxbtmyxdu3aWadOnVy3BdE5pFChQjZ79mzLnz+/3XLLLS6PkQbd5BdZS48ePbzTTjvNK1mypNeoUSOvffv23o4dO9xrS5Ys8W699VbvvPPO84YPH57ZSU04P/30k3fZZZd5l19+uffoo496LVu29CpUqOA1a9bMO3DgQGYnL8tZvny599dff7nHn3zyiVe9enXvjTfe8J5//nmvWLFiLi/LlCnjvfTSS+RfGp588knviiuu8K655hpv165dEa/NnTvXlb9TTjnFO/fcc72TTz7Z+/vvvzMtrYnglVde8UqVKuU9+OCD3qpVqyJeGz16tHfTTTdRFsM888wz3t69e91jv2z973//82rVquXVrVvX+/333926gwcPuv937tzpHX/88d4tt9ySianO2gicspgBAwZ4ZcuW9WbNmuUKcqdOnbyCBQu6g+62bdvcNt9++6070Xfs2DFU2BHpzz//9DZv3uwOAhJ+MlIe64DhU1Dq5yP5+a8PP/zQq1KlitemTRsXcErPnj293r17u8fTp093r+XIkcO77bbbMjm1WUf0SVuBpvJIAeb333+fYnuduB544AGXr345/eeffzIsvVmdAnf/5O577rnnvPLly3sPP/ywt3r16lT/LtmDp+jv379/f++FF14IHRMVPJ144oneBRdc4K1bty7i+Ldnzx7K4CEQOGUhK1as8Bo2bOh99NFH7vmnn37qHXPMMV7r1q29008/3dWO+DVPOpH5OwYn+5RX+GeffbZXs2ZN7/zzz/d+++03t37//v3u/7feestd2fvPfcl+oE2tHL388sve1Vdf7RUuXNgbN26cN2TIEHegXbp0qXt97dq13syZMznIpkIXODoB+UGogqe7777b27BhwyHznBqnf/Xt29dr0KCBV6RIEa9Dhw7e5MmTQ68NHjzY1Yw88sgj3q+//pqp6UwEd9xxhyuDr732WorgqUmTJimCJ2G/Th2BUxbz5ptvutqSL774witXrpxrAhE1z+XMmdM13fmFXpL9ZB+tV69eXunSpb2xY8d6U6ZM8erUqeOdcMIJoRO9f7JXM+jChQszNa1ZSXg5Wrlypbdo0SJv9+7dESewSpUqeffcc49XvHhx78ILL/T27dsX8R4cZP81YcIE79RTT/VGjRoVaiZ5++233YmrW7du3saNG0Pbsg+nTk3pqqVTjd3s2bO9qlWrugshXfj4FMjnypUrdJzEocuUyl6ePHm8V199NSJ4Oumkk7waNWq4WnocHoFTFqD+Ivfff3/EOlXd33777aGT0xNPPOFdfPHFruBzoE2dmo4UKM2ZMyd0la8rVZ3ASpQoEQqe1G/nqquuIh//v/ArTAWeasY89thjXf+le++9N/T6Z5995sqp+t8pAFCQj9Rt377du/LKK7369eu7K3w/eFKtnfKue/fu3vr16zM7mVl6X65WrZoLmGTevHle3rx5XfB0zjnneO+++25oWwWkBO3/Cj+uqU/sd999F3ER1KVLlxTBk5qQ1R2EfAyGwCmTKTBSZ/CmTZt6W7duDa2/+eabXRW179prr3Xt0z5O+il9+eWXXr9+/dxj1TapA6k60P/yyy+u1kk1JtG1TBwoIps4VRP3+eefe5s2bfJuvPFGF3jOnz8/tI2amXQya9WqFXl3mH1RJ6UWLVq4E3148DR+/HgXPA0bNiyDU5o4fvzxx9DgF3VZUC2nOn7/8ccfroxqcIyakcNRHiMpOFcznAJO7ct+FxA/eMqXL58rl373Dx/5eHgETlnAggULXF8m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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk4AAAGGCAYAAACNCg6xAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAARZJJREFUeJzt3QncTOX///GPfSlb9rRQRJYkUlKUlEq0p5USqSjRRjvfLKlEEknyKyUSWhQhomhBSqTdlj1x24Xzf7yv/meauRfOcM8999zzej4ew8yZc89cc82Zcz7nWj4nl+d5ngEAAOCgch98FQAAAAiBEwAAQEAETgAAAAEROAEAAARE4AQAABAQgRMAAEBABE4AAAABETgBAAAEROAEAAAQEIETEAfLli2zXLly2ciRI+NdFGQTY8eOtaOOOsq2bdsWs/eoWLGi3XLLLaHHkydPtiOPPNI2bNgQs/cEchoCJ2QKBQAKBPxbwYIF7aSTTrJOnTrZunXrLBEtWbLEnnzySRfkHKq33nrLBgwYYNmJDpw6WCaqHTt2uO9l5syZllPs27fPnnjiCbv77ruz9Lu56KKLrHLlytanTx+L9zYZvv8oUKCA2388/vjjtmvXroh1H3roIWvYsKG7nX766TZnzpxMKcPu3bvdax999NFWqFAhO+OMM2zq1KmB//7tt9+20047ze37Spcubbfddptt3Lgx3XW1T+zQoYNVqFDBra+AVuuH0zYeXifh+1bEV944vz9ymJ49e1qlSpXczu7zzz+3IUOG2EcffWQ//PCDFS5c2BItcOrRo4ede+65bsd2qIGTPvu9994bsfz444+3nTt3Wr58+TKptMlDgZO+F9F3kxN88MEH9tNPP9ntt9+e5e+tA/j999/v6rRIkSIWLwqWhg8f7u5v2bLF3nvvPfvf//5nv/32m7355puh9RRgPP300+6+TkpuvPFG++OPPzIleBs3bpz7rVapUsWdDF5yySU2Y8YMO/vssw/4t9rP3XXXXXb++edb//79bdWqVTZw4ECbN2+effXVVxHBzsqVK13QJ3fccYcLnlavXm1ff/11hq8dHkznyZPnsD8rDpMu8gscrtdee00Xi/a++eabiOVdu3Z1y996663Dfo/t27d7Wemdd95xZZ8xY8Yhv0bz5s29448/3stO2rRp4x1xxBFeotm3b5+3c+dOb8OGDe57eeKJJ7ycomXLlt7ZZ58d8/fRtqjvP9y6deu8PHnyeK+++qqXnbbJ/fv3e2eeeaaXK1cub+3aten+Xf/+/b0TTjjhsN//q6++ctvUM888E1qmbe3EE0/0GjRocMC/3b17t1e8eHGvUaNGrsy+Dz74wL3mCy+8ELH+xRdf7FWqVMnbuHHjAV9X27f+Xts7she66hBTTZo0cf+HnxGOGjXK6tat65rDNabjuuuuc2dh4dSSULNmTZs/f741atTItVY9/PDDobFBzz77rA0ePNhOOOEE99yFF17oXsPzPHeWeswxx7jXv+yyy2zTpk0Rr62/VzP4gcZ/6GzzmmuucffPO++8UDO53z2ks+HmzZu7Zn2dKZ944onufdXlEv4ZJk2aZMuXLw/9vd9yldEYp08//dTOOeccO+KII6x48eKu/D/++GO6Tfi//vqrK6/WK1asmN16662uNeZQqFyXXnqp+3z16tVzdVerVq3Q5x0/frx7rDNnfXfffvttut1/v//+uzVr1syVX3WjFkh9J+G2b99u9913nx177LGu7qpWreq+z9Tr6TOqq1etDTVq1HDrDh061HWDiFpI/Hr1v8/vv//elUXbhcparlw5a9u2rf3111+HVYfaZuvXr++2tRIlSrht8pNPPolY5+OPPw59d2q50faxePHig9a9Wmc11qhp06YRy7X9a9tLbf/+/a6V4uqrrw4tU/2dddZZVrJkSffd6TtS60kQZcqUsVNOOcVt09mJvh+19Gi70HaVmlpy9T2qhedwqa7UkhPe4qftR61bc+fOTbN/Sl2OzZs3W6tWrVyZffo96TehLjzf0qVL3XbywAMPuO9K3/0///xzwLLp86ekpKT5fSB+6KpDTKmZXbSTkF69etljjz1m1157rbVr184NSh00aJA7EOlgrAOYTwe7iy++2AVWN910k5UtWzb0nA6me/bscWNCFBj169fPvaYCNR3sNVZBB0W9trohRowYEVW5VZ577rnHXnjhBRewnXzyyW65/78CHu0Uu3bt6v5XwKPxGNrBPfPMM26dRx55xHU5qNn++eefd8sONH5l2rRp7vPqoK8DgrryVH416y9YsCBNd6E+r7pFNT5Fz6ubQwdBvxsjWqqvG264wXXdqL51MG7RooULVlQH6ooQvZ/eW11LuXP/d+6loFFjZs4880z3fSgY0LidvXv3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P9atWrVqXseOHd306/B0BJoinNF04/AMv6KpxVquFAIHK5emlT/00ENeqVKlXPqAZs2auenP6U3VfuWVV1xmYqVRCJ/C/MUXX7isxpqqf/TRR3sPPvhgaPp++DTnbdu2eTfccIObrq7n/NQE6aUjEKVzaNiwoXvdokWLei1atPCWLFkSKKOw/1n12oeSjkCpA1LT6+m7Odh34L+mpopfeOGFrl7Lli3rypp6Gr+m73fp0sXVW758+dz0ar1W+JTzjN7bp7QJdevWdakOwlMTKO2FUgeovpUK4JprrvFWr16dJn1BtHU4YsQIr06dOl6BAgW8EiVKuO1z6tSpEevoe9e2pPctWLCgm15+yy23ePPmzfMOZvz48W5K+4oVK9J9XtuEytWuXbt0n1fWb9Wjyqffkz6H/xnDpbeNDxkyxH1fKSkpXnbMZq9tSr+/9NIoZCZlCr///vu9cuXKuXo8/fTTvcmTJ6dZz0+VEu7DDz/06tev7xUpUsTVpfYNY8eOzfC9lCJDqVP0PvqdKO1A6vrXd129enX3mvqdVK5c2e234vk94V+59E88AzcAic+/zpc/3RrRUTeNWtHUuqTWrayk8TLqQkqdfBRA+hjjBABxpi5hddOpiy0rg091rWrwvLqoAARDixOAw0aLE4BkQYsTAABAQLQ4AQAABESLEwAAQEAETgAAAAElXQJMZf9dvXq1S7wY9HIYAAAg59KoJV0KSoltwy/AnJ6kC5wUNKW+2jsAAMDKlSvTXGzbkj1w8i8sqsoJv5gjAABITikpKa5RJfzi4xlJusDJ755T0ETgBAAAfEGG8DA4HAAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgJLukis5yta1/96CKlLu3xsAADgkBE6JbN5rZp/1Db5+425m53WPZYkAAMjRCJwSWb1bzape/N/jvTvNRlz07/22k83yFopcn9YmAAAOC4FTIkvd9bZn+3/3y51ilv+IuBQLAICcisHhAAAAARE4AQAABETgBAAAEBBjnGKgYrdJcXnfQrbLfiz47/2TH59sO+3/P4iDZX2bx+29AQCIFVqcAAAAAiJwAgAACIjACQAAICACJwAAgIAYHJ7AStvfVibX5tDjgrYndL96ruW2y/JHrL/eK24brESWlhEAgJyEwCmB3Zh3ut2bd3y6z71boEeaZQP2XmkD9l6dBSUDACBnInBKYG/uPd+m7qsbeH21OAEAgENH4JTA1O22waPrDQCArMLgcAAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAIBECJz69Oljp59+uhUpUsTKlCljl19+uf30008H/bt33nnHqlWrZgULFrRatWrZRx99lCXlBQAAyS2ugdNnn31mHTt2tC+//NKmTp1q//zzj1144YW2ffv2DP9mzpw5dv3119ttt91m3377rQu2dPvhhx+ytOwAACD55PI8z7NsYsOGDa7lSQFVo0aN0l2nVatWLrD68MMPQ8vOPPNMO/XUU23o0KEHfY+UlBQrVqyYbdmyxYoWLWqxULHbJEt2y/o2j3cRAAAIJJrYIFuNcVKB5aijjspwnblz51rTpk0jljVr1swtT8/u3btdhYTfAAAADkW2CZz2799v9957rzVs2NBq1qyZ4Xpr1661smXLRizTYy3PaByVokj/duyxx2Z62QEAQHLINoGTxjppnNLbb7+dqa/bvXt315Ll31auXJmprw8AAJJHtrhWXadOndyYpVmzZtkxxxxzwHXLlStn69ati1imx1qengIFCrgbAABAQrc4aVy6gqYJEybYp59+apUqVTro3zRo0MCmT58esUwz8rQcAAAgx7Y4qXvurbfesvfee8/lcvLHKWksUqFChdz91q1bW4UKFdxYJencubM1btzYnnvuOWvevLnr2ps3b54NGzYsnh8FAAAkgbi2OA0ZMsSNOzr33HOtfPnyoduYMWNC66xYscLWrFkTenzWWWe5YEuBUu3atW3cuHE2ceLEAw4oBwAASPgWpyAppGbOnJlm2TXXXONuAAAASTmrDgAAILsjcAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAICACJwAAAACInACAAAIiMAJAAAgIAInAACAgAicAAAAAiJwAgAAyIrAaffu3ZlXEgAAgJwUOH388cfWpk0bO+GE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Oumkk2zdunVplq9fv97leAIAAMipog6c+vTpY/fcc4+NGzfOddfppvv33nuvG+uUkpISugEAACR1V92ll17q/r/22mstV65c7r7nee7/Fi1ahB7rOc2+AwAASNrAacaMGbEpCQAAQE4LnBo3bhybkgAAAGRzh5SxcteuXfb999+7AeH79++PeE45ngAAAHKiqAOnyZMnW+vWrW3jxo1pnmNcEwAAyMminlV399132zXXXGNr1qxxrU3hN4ImAACQk0UdOCmHU9euXa1s2bKxKREAAEBOCZyuvvpqmzlzZmxKAwAAkJPGOL344ouuq2727NlWq1Yty5cvX8TzSo4JAACQE0UdOI0ePdo++eQTK1iwoGt58pNgiu4TOAEAgJwq6sDpkUcesR49eli3bt0sd+6oe/oAAAASVtSRz549e6xVq1YETQAAIOlEHf20adPGxowZE5vSAAAA5KSuOuVq6tevn02ZMsVOOeWUNIPD+/fvn5nlAwAASNzAadGiRVanTh13/4cffoh4LnygOAAAgCV74DRjxozYlAQAACCbY4Q3AABAZrc4XXnllYHWGz9+fNCXBAAAyJmBU7FixWJbEgAAgJwSOL322muxLQkAAEA2xxgnAACAgAicAAAAAiJwAgAACIjACQAAICACJwAAgIAInAAAAAIicAIAAAiIwAkAACAgAicAAIBECpwGDx5sFStWtIIFC9oZZ5xhX3/9dYbrjhw50nLlyhVx098BAADk+MBpzJgx1rVrV3viiSdswYIFVrt2bWvWrJmtX78+w78pWrSorVmzJnRbvnx5lpYZAAAkp7gHTv3797f27dvbrbfeatWrV7ehQ4da4cKFbcSIERn+jVqZypUrF7qVLVs2S8sMAACSU1wDpz179tj8+fOtadOm/xUod273eO7cuRn+3bZt2+z444+3Y4891i677DJbvHhxFpUYAAAks7gGThs3brR9+/alaTHS47Vr16b7N1WrVnWtUe+9956NGjXK9u/fb2eddZatWrUq3fV3795tKSkpETcAAICE7KqLVoMGDax169Z26qmnWuPGjW38+PFWunRpe/nll9Ndv0+fPlasWLHQTa1UAAAACRc4lSpVyvLkyWPr1q2LWK7HGrsURL58+axOnTr266+/pvt89+7dbcuWLaHbypUrM6XsAAAg+cQ1cMqfP7/VrVvXpk+fHlqm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NmHCBJddHYdGl+i58847412MhPbnn3+6yx0NHjw43kVJKOvXr7errrrKmjVr5q612a9fP3cf0QdNfgD/+++/288//+zucyJ0aMaPH+8uYfbpp5/ali1b4l2chEDglAA++OAD69Chg02aNMmOOeYYt4wm/kOjS/msXr3a1q1bxxlqQPv27Yt47F87cvTo0TZ//vy4lSvRlClTxmbPnu1OgnRtzTlz5lj16tVt79698S5aQvGDpu7du9t5551njRo1sgsvvNCWL18e76IlHNXhLbfcYqNGjXJB/GOPPWaLFi2Kd7GyPQKnBHDcccdZjRo13LX8Pvroo9DOg+ApehUrVnRnpikpKe7/1EEB0sqTJ4/7f9y4ce4C3HLZZZdZvnz57JNPPnGP2RYzFl43Cpq03RUpUsRda1PBe968edPUH0F9WuG/1bFjx7rWY7WUDBkyxJ0IXXrppfb999/HtYyJRCc9CxYssClTpti3337rgqepU6faCy+8QD0mwrXqcGC1a9d21wjSAUxn+aVKlbJbb701FDwxUPzAtCP45ptv3AWiy5cv71qddADTBaL9oCD8gEWTf1rauV577bXWpEkTd51IXZz7rrvucmerCqLUcsK2mFb4RI6HHnrIFi9e7FqdVFc60F988cXuoubh9aYAIfV2mcx2797tro/m18m7775rf/31l6vPq6++2i274IILrHHjxnbDDTe4fWStWrXiXOrsTcHm559/biVKlLDTTz/dLdNvWp588km3D7z77rupxwywl8umdKDXwUqR/65du6xatWr24IMPupan4cOH28iRI9162uFydpqxTZs2uXEQGzdudDvUzp072y+//GLdunWz888/3x599FE3U1Fnr0LQ9K/ULSBVq1a1SpUque6QVatWWYsWLezEE090By6NGdu2bRtBUzr87WnJkiXuQKWukVNOOcWNUxwzZoz98MMPbryY312nLnn9vvEvBUPhExH+/vtvu+2226xjx46uy120/zvyyCNt1qxZVrBgQbvppptcSwoytnXrVteCrHrS2FmfgqcePXq4bmRNXvjtt9/iWs5sSxf5RfbSrVs3r2rVql6pUqW8Ro0aee3atfO2bt3qnlu4cKF38803e+ecc443ePDgeBc14fzyyy/exRdf7F1yySXeY4895l177bXescce6zVv3tzbt29fvIuX7SxevNj766+/3P2PP/7Yq1mzpvf66697L7zwgleiRAlXl2XLlvVefvll6i8DvXv39i699FLvyiuv9LZv3x7x3Oeff+62v8qVK3tnnnmmd+KJJ3r//PNP3Mqa3Tz77LPerl273H2/Xn7++Wevdu3aXr169bxVq1a5Zfv373f/b9u2zTvmmGO8m266KY6lTgyvvPKKV7p0ae/BBx/0li9fHvHcyJEjvRtuuIHfdAYInLKZPn36eOXKlfM+++wztzPo2LGjV7hwYbfT3bJli1vnu+++cwf6Dh06hHYYiLR69Wpv06ZNbkcq4Qcj1bF2uj4FpX49Up//ef/9971q1ap5bdq0cQGndO/e3XviiSfc/U8//dQ9lytXLu/WW2+Nc2mzj9QHGwWaqiMFmEuWLEmzvg7+999/v6tXfzvdu3evl8xS12GvXr28F198MfR7VvB0/PHHe+edd563du3aiN/uzp07k77+0qMTID/Q9D3//PNehQoVvIcffthbsWJFun9H8JQWgVM2snTpUu/ss8/2PvjgA/d4ypQp3hFHHOG1bt3aO/nkk13riN/ypAOZv0FzsE97hl+/fn3vlFNO8c4991xv2bJlbvmePXvc/2+99ZY7s/cf+5J9B5HedjRs2DDviiuu8IoWLeqNHj3aGzBggDtYLVq0yD2/Zs0ab+bMmRyo0qETHB3E/SBUwdNdd93lrV+//oB1TotTWrfffrurvxEjRqQJnpo0aZImeBK2yf/06NHDa9iwoVesWDGvffv23kcffRR6rn///q6V7tFHH/V+//33uJYzURA4ZTNvvvmmay354osvvPLly7suEFH3XO7cuV3Xnb/jkGQ/2Kf2yCOPeGXKlPFGjRrlTZ482atbt6533HHHhQ70/sFe3aDz5s2La1mzk/Dt6I8//vDmz5/v7dixI2LHW6lSJa9Tp07eUUcd5Z1//vne7t27I16DA9V/xo0b55100kne8OHDQ11Nb7/9tjv433fffd6GDRtC6/IbjpRRfaje8uXL57366qsRwdMJJ5zg1apVy7UwIy0NSVBrp1o+Z82a5VWvXt2dUOoE0qcTojx58oSONzgwAqdsQONFunTpErFMTfdt27YNHZyeeuop74ILLnA7D3a06VPXkQKl2bNnh87ydYalA1jJkiVDwZPG7Vx22WXU4/8XfpauwFPdmEWKFHHjl+6+++7Q85988onb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", "text/plain": [ "
" ] @@ -648,16 +645,7 @@ } ], "source": [ - "# Permutation-based\n", - "plt.figure(figsize=(6,4))\n", - "x = np.arange(len(feat_order))\n", - "plt.bar(x, imp_perm_mean)\n", - "plt.errorbar(x, imp_perm_mean, yerr=imp_perm_std, fmt=\"none\", capsize=4, ecolor=\"black\", zorder=3)\n", - "plt.xticks(x, feat_order, rotation=45, ha=\"right\")\n", - "plt.ylabel(\"Importance (mean)\")\n", - "plt.title(\"Feature Importance (Permutation on Test)\")\n", - "plt.tight_layout()\n", - "plt.show()" + "perm_df, val_r2 = fi.permutation_importance(val_size=0.2, n_repeats=20, plot=True)" ] } ], diff --git a/modularml/preprocessing/__init__.py b/modularml/preprocessing/__init__.py index e03f099..62f79f1 100644 --- a/modularml/preprocessing/__init__.py +++ b/modularml/preprocessing/__init__.py @@ -44,3 +44,7 @@ "absolute": Absolute, "segmented": SegmentedScaler, } + + +from .feature_importance import FeatureImportance + diff --git a/modularml/preprocessing/feature_importance.py b/modularml/preprocessing/feature_importance.py new file mode 100644 index 0000000..2f60bf7 --- /dev/null +++ b/modularml/preprocessing/feature_importance.py @@ -0,0 +1,77 @@ +# preprocessing/feature_importance.py +from __future__ import annotations +import numpy as np +import pandas as pd +from typing import Optional, Sequence, Tuple, Union +from sklearn.ensemble import RandomForestRegressor +from sklearn.model_selection import GroupShuffleSplit, ShuffleSplit +from sklearn.inspection import permutation_importance as _perm +import lightgbm as lgb + +class FeatureImportance: + def __init__(self, estimator: Union[str, object] = "rf", random_state: int = 42, n_jobs: int = -1, **est_kwargs): + self.estimator_spec = estimator + self.random_state = random_state + self.n_jobs = n_jobs + self.est_kwargs = est_kwargs + self.X = self.y = self.groups = None + self.feature_names: Sequence[str] = () + + def fit(self, X: np.ndarray, y: np.ndarray, feature_names: Sequence[str], groups: Optional[np.ndarray] = None): + self.X = np.asarray(X, float) + self.y = np.asarray(y, float) + self.feature_names = list(feature_names) + self.groups = (np.asarray(groups) if groups is not None else None) + return self + + def model_importance(self, plot: bool = False): + est = self._make_estimator() + est.fit(self.X, self.y) + + # RF / most trees: + imp = getattr(est, "feature_importances_", None) + if imp is None and est.__class__.__name__.lower().startswith("lgbm") and hasattr(est, "booster_"): + # LightGBM (gain) + imp = est.booster_.feature_importance(importance_type="gain") + imp = np.asarray(imp if imp is not None else np.zeros(len(self.feature_names)), float) + + s = pd.Series(imp, index=self.feature_names, name="model_importance").sort_values(ascending=False) + if plot: + import matplotlib.pyplot as plt + x = np.arange(len(s)) + plt.figure(figsize=(6,4)); plt.bar(x, s.values); plt.xticks(x, s.index, rotation=45, ha="right") + plt.ylabel("Importance"); plt.title("Model-based Importance"); plt.tight_layout(); plt.show() + return s + + def permutation_importance(self, val_size: float = 0.2, n_repeats: int = 20, plot: bool = False) -> Tuple[pd.DataFrame, float]: + # train→val split inside training (group-aware if groups given) + if self.groups is not None: + (tr, va), = GroupShuffleSplit(1, test_size=val_size, random_state=self.random_state).split(self.X, groups=self.groups) + else: + tr, va = next(ShuffleSplit(1, test_size=val_size, random_state=self.random_state).split(self.X)) + Xtr, Ytr, Xva, Yva = self.X[tr], self.y[tr], self.X[va], self.y[va] + + est = self._make_estimator(); est.fit(Xtr, Ytr) + val_r2 = float(est.score(Xva, Yva)) + + perm = _perm(est, Xva, Yva, n_repeats=n_repeats, random_state=self.random_state, n_jobs=self.n_jobs) + df = (pd.DataFrame({"feature": self.feature_names, "perm_mean": perm.importances_mean, "perm_std": perm.importances_std}) + .set_index("feature").sort_values("perm_mean", ascending=False)) + + if plot: + import matplotlib.pyplot as plt + x = np.arange(len(df)); y = df["perm_mean"].values; e = df["perm_std"].values + plt.figure(figsize=(6,4)); plt.bar(x, y); plt.errorbar(x, y, yerr=e, fmt="none", capsize=4, ecolor="tab:orange") + plt.xticks(x, df.index, rotation=45, ha="right"); plt.ylabel("Importance (mean)") + plt.title(f"Permutation Importance (val) — R²={val_r2:.3f}"); plt.tight_layout(); plt.show() + return df, val_r2 + + def _make_estimator(self): + if not isinstance(self.estimator_spec, str): + return self.estimator_spec + name = self.estimator_spec.lower() + if name in ("rf", "random_forest", "randomforest"): + return RandomForestRegressor(random_state=self.random_state, n_jobs=self.n_jobs, **self.est_kwargs) + if name in ("lgbm", "lightgbm"): + return lgb.LGBMRegressor(random_state=self.random_state, n_jobs=self.n_jobs, **self.est_kwargs) + raise ValueError("estimator must be 'rf', 'lgbm', or a ready estimator")