diff --git a/notebooks/[WIP] Untitled.ipynb b/notebooks/[WIP] Untitled.ipynb index 8aa5872..d7ffb4f 100644 --- a/notebooks/[WIP] Untitled.ipynb +++ b/notebooks/[WIP] Untitled.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 22, + "execution_count": 259, "id": "f13010f3", "metadata": {}, "outputs": [], @@ -13,6 +13,9 @@ "import numpy as np\n", "import pandas as pd\n", "import param\n", + "#from pycaret.utils import check_metric\n", + "\n", + "#from feature_selection.run_pycaret_setup import run_pycaret_setup\n", "\n", "\n", "class FeatureSelection(param.Parameterized):\n", @@ -103,10 +106,10 @@ " target = param.String(\"goal_2.5\")\n", " number_features = param.Number(\n", " 0.5,\n", - " bounds=(0, None),\n", - " inclusive_bounds=(False, True),\n", - " doc=\"Number of features selected each iteration. Only the first nth features \"\n", - " \"(where n is given by 'number_features') will be kept for the next iteration.\",\n", + " bounds=(0, 1),\n", + " inclusive_bounds=(False, False),\n", + " doc=\"Number of features (percentage) selected each iteration. Only the first nth \"\n", + " \"features will be kept for the next iteration.\",\n", " )\n", " target_features = param.Number(\n", " 0.3,\n", @@ -115,12 +118,11 @@ " doc=\"Final total number of features. The goal of the package is to reduce \"\n", " \"the incoming columns of the dataset to this 'target_features' number.\",\n", " )\n", - " feature_division = param.Number(3, bounds=(1, 100))\n", " ## Metric parameters\n", " filter_metrics = param.Dict(_filter_metric)\n", " ## Model setup and model optimization parameters\n", " numerics = param.List(_numerics)\n", - " ignore_features = param.List(default=None, allow_None=True)\n", + " ignore_features = param.List(default=[], allow_None=True)\n", " setup_kwargs = param.Dict(_setup_kwargs)\n", " include = param.List(default=None, item_type=str, allow_None=True)\n", " exclude = param.List([\"qda\", \"knn\", \"nb\"], item_type=str)\n", @@ -144,10 +146,12 @@ " dataset = dataset.copy()\n", " # Compute the upper bound of number_features, target_features, number_models\n", " total_features = dataset.shape[1]\n", - " self.param.number_features.bounds = (0, total_features)\n", " self.param.target_features.bounds = (0, total_features)\n", " if \"include\" in kwargs:\n", - " self.param.number_models.bounds = (2, len(include))\n", + " print('hola')\n", + " self.param.number_models.default = len(kwargs[\"include\"])\n", + " self.param.number_models.bounds = (0, len(kwargs[\"include\"]))\n", + " print(self.param.number_models.bounds)\n", " # Call super\n", " super(FeatureSelection, self).__init__(dataset=dataset, **kwargs)\n", " # Get the features of the dataframe\n", @@ -158,7 +162,7 @@ " number_features=self.target_features, features=self.feature_list\n", " )\n", " # Get the evaluator and the arguments. Depends on the \"include\" parameter\n", - " self.obj, self.args = self._decide_model_eval()\n", + " self._training_function, self._args = self._decide_model_eval()\n", " # Get all the columns whose type is numeric\n", " self.numeric_features = self._compute_numeric_features(df=self.dataset[self.feature_list])\n", "\n", @@ -180,63 +184,42 @@ " list.\n", " \"\"\"\n", " args = {\"n_select\": self.number_models, \"sort\": self.sort, \"verbose\": False}\n", - " obj = np.random.randint\n", + " training_function = np.random.randint\n", " if not self.include:\n", " args[\"exclude\"] = self.exclude\n", " elif len(self.include) == 1:\n", - " obj = range\n", - " args = {\"estimator\": self.include[0]}\n", + " training_function = lambda *rgs, **kwargs: [range(*rgs, **kwargs)]\n", + " args = {\"estimator\": self.include[0], \"verbose\": False}\n", " else:\n", " args[\"include\"] = self.include\n", - " return obj, args\n", + " return training_function, args\n", "\n", " @staticmethod\n", " def calculate_number_features(\n", " number_features: Union[int, float], features: Union[pd.DataFrame, List]\n", " ) -> int:\n", " n_features = (\n", - " int(number_features) if (number_features >= 1) else int(number_features * len(features))\n", + " int(number_features)\n", + " if (number_features >= 1)\n", + " else int(number_features * len(features))\n", " )\n", - " return n_features\n", - "\n", - " def train_model(self):\n", - " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", - " # Selected dataset\n", - " selected_cols = self.feature_list + [self.target]\n", - " train_data = self.dataset[selected_cols] if self.x_df.empty else self.x_df[selected_cols]\n", - " # Numeric features\n", - " self.setup_kwargs[\"numeric_features\"] = [\n", - " c for c in self.numeric_features if c in self.feature_list\n", - " ]\n", - " # Ignore features\n", - " self.setup_kwargs[\"ignore_features\"] = [\n", - " c for c in self.ignore_features if c in self.feature_list\n", - " ]\n", - " # Initialize pycaret setup\n", - " setup(train_data=train_data, target=self.target, **self.setup_kwargs)\n", - " # Get train dataset and preprocessed dataframe\n", - " self.x_train = get_config(\"X_train\")\n", - " if self.x_df.empty: # TODO change x_df by dataset and add flag?\n", - " self.x_df = pd.concat([get_config(\"X\"), get_config(\"y\")], axis=1)\n", - " self.setup_kwargs[\"preprocess\"] = False # Turn off preprocessing\n", - " # Compare models\n", - " self.top_models = self.obj(**self.args)" + " return n_features" ] }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 260, "id": "028d5b40", "metadata": {}, "outputs": [], "source": [ "dataset = pd.DataFrame({'a': [1,3,3,4,5], 'b': [13,3,4,4,5], 'c': ['a', 'b', 'c', 'd', 'd']})\n", - "a = FeatureSelection(dataset, target='c', target_features=1)" + "pepe = FeatureSelection(dataset, target='c', target_features=1)" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 139, "id": "c8453ac0", "metadata": {}, "outputs": [ @@ -246,7 +229,7 @@ "['a', 'b']" ] }, - "execution_count": 31, + "execution_count": 139, "metadata": {}, "output_type": "execute_result" } @@ -257,11 +240,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "3bd6c126", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/vicentearjona/Library/Python/3.8/lib/python/site-packages/IPython/core/interactiveshell.py:3441: DtypeWarning: Columns (2012,2016) have mixed types.Specify dtype option on import or set low_memory=False.\n", + " exec(code_obj, self.user_global_ns, self.user_ns)\n" + ] + } + ], + "source": [ + "predictions = pd.read_csv('predictions.csv')" + ] }, { "cell_type": "code", @@ -281,7 +275,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "id": "aba4a1d2-96b4-444a-9648-05c48864faae", "metadata": {}, "outputs": [ @@ -796,396 +790,6 @@ "pn.Row(a.param)" ] }, - { - "cell_type": "code", - "execution_count": 35, - "id": "63e48759-5207-4631-a004-574ff32eb6e1", - "metadata": {}, - "outputs": [], - "source": [ - "from itertools import product\n", - "from typing import Dict, List, Optional, Union\n", - "\n", - "import numpy as np\n", - "import pandas as pd\n", - "import param\n", - "#from pycaret.classification import compare_models, get_config, predict_model, tune_model\n", - "#from pycaret.utils import check_metric\n", - "\n", - "#from feature_selection.run_pycaret_setup import run_pycaret_setup\n", - "\n", - "\n", - "class FeatureSelection(param.Parameterized):\n", - "\n", - " # Class attributes\n", - " model_class_to_name = {\n", - " \"RidgeClassifier\": \"ridge\",\n", - " \"LogisticRegression\": \"lr\",\n", - " \"LinearDiscriminantAnalysis\": \"lda\",\n", - " \"GradientBoostingClassifier\": \"gbc\",\n", - " \"QuadraticDiscriminantAnalysis\": \"qda\",\n", - " \"LGBMClassifier\": \"lightgbm\",\n", - " \"AdaBoostClassifier\": \"ada\",\n", - " \"RandomForestClassifier\": \"rf\",\n", - " \"ExtraTreesClassifier\": \"et\",\n", - " \"GaussianNB\": \"nb\",\n", - " \"DecisionTreeClassifier\": \"dt\",\n", - " \"KNeighborsClassifier\": \"knn\",\n", - " \"SGDClassifier\": \"svm\",\n", - " \"CatBoostClassifier\": \"catboost\",\n", - " \"SVC\": \"rbfsvm\",\n", - " \"GaussianProcessClassifier\": \"gpc\",\n", - " \"MLPClassifier\": \"mlp\",\n", - " \"XGBClassifier\": \"xgboost\",\n", - " }\n", - "\n", - " metrics_list = [\"Accuracy\", \"AUC\", \"Recall\", \"Precision\", \"F1\", \"Kappa\", \"MCC\"]\n", - "\n", - " # Private class attributes\n", - " _filter_metric = {\n", - " \"Accuracy\": 0.5,\n", - " \"AUC\": 0.5,\n", - " \"Recall\": 0.6,\n", - " \"Precision\": 0.6,\n", - " \"F1\": 0.6,\n", - " \"Kappa\": 0.1,\n", - " \"MCC\": 0.1,\n", - " }\n", - "\n", - " _setup_kwargs = dict(\n", - " preprocess=True,\n", - " train_size=0.75,\n", - " # test_data=test_data,\n", - " session_id=123,\n", - " normalize=True,\n", - " transformation=True,\n", - " ignore_low_variance=True,\n", - " remove_multicollinearity=False,\n", - " multicollinearity_threshold=0.4,\n", - " n_jobs=-1,\n", - " use_gpu=False,\n", - " profile=False,\n", - " ignore_features=None,\n", - " fold_strategy=\"timeseries\",\n", - " remove_perfect_collinearity=True,\n", - " create_clusters=False,\n", - " fold=4,\n", - " feature_selection=False,\n", - " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", - " feature_selection_threshold=0.4,\n", - " combine_rare_levels=False,\n", - " rare_level_threshold=0.02,\n", - " pca=False,\n", - " pca_method=\"kernel\",\n", - " pca_components=30,\n", - " polynomial_features=False,\n", - " polynomial_degree=2,\n", - " polynomial_threshold=0.01,\n", - " trigonometry_features=False,\n", - " remove_outliers=False,\n", - " outliers_threshold=0.01,\n", - " feature_ratio=False,\n", - " feature_interaction=False,\n", - " # Makes everything slow AF. use to find out possibly interesting features\n", - " interaction_threshold=0.01,\n", - " fix_imbalance=False,\n", - " log_experiment=False,\n", - " verbose=False,\n", - " silent=True,\n", - " experiment_name=\"lagstest\",\n", - " )\n", - "\n", - " _numerics = [\"int16\", \"int32\", \"int64\", \"float16\", \"float32\", \"float64\", \"int\", \"float\"]\n", - "\n", - " # Init values\n", - " ## Feature selection parameters\n", - " target = param.String(\"goal_2.5\")\n", - " number_features = param.Number(0.5, bounds=(0, None), inclusive_bounds=(False, True))\n", - " target_features = param.Number(0.3, bounds=(0, None), inclusive_bounds=(False, True))\n", - " feature_division = param.Number(3, bounds=(1, 100))\n", - " ## Metric parameters\n", - " filter_metrics = param.Dict(_filter_metric)\n", - " ## Model setup and model optimization parameters\n", - " numerics = param.List(_numerics)\n", - " ignore_features = param.List(default=None, allow_None=True)\n", - " setup_kwargs = param.Dict(_setup_kwargs)\n", - " include = param.List(default=None, item_type=str, allow_None=True)\n", - " exclude = param.List([\"qda\", \"knn\", \"nb\"], item_type=str)\n", - " sort = param.String(\"AUC\")\n", - " number_models = param.Integer(10, bounds=(2, 13))\n", - " top_models = param.List(default=None, allow_None=True)\n", - " optimize = param.Boolean(False)\n", - " opt_list = param.List([\"Accuracy\", \"Precision\", \"Recall\", \"F1\", \"AUC\"], item_type=str)\n", - " ## Class selectors\n", - " dataset = param.ClassSelector(class_=pd.DataFrame)\n", - " dict_models = param.ClassSelector(class_=dict)\n", - " tune_dict_models = param.ClassSelector(class_=dict)\n", - " x_train = param.ClassSelector(class_=pd.DataFrame)\n", - " model_df = param.ClassSelector(class_=pd.DataFrame)\n", - " model_tuned_df = param.ClassSelector(class_=pd.DataFrame)\n", - " features_df = param.ClassSelector(class_=pd.DataFrame)\n", - "\n", - " def __init__(self, dataset: pd.DataFrame, **kwargs):\n", - " # Compute the upper bound of number_features and target_features\n", - " total_features = dataset.shape[1]\n", - " self.param.number_features.bounds = (0, total_features)\n", - " self.param.target_features.bounds = (0, total_features)\n", - " # Call super\n", - " super(FeatureSelection, self).__init__(dataset=dataset, **kwargs)\n", - " # Get the features of the dataframe\n", - " self.feature_list = self.dataset.columns.tolist()\n", - " self.feature_list.remove(self.target) # target column should not be counted\n", - " # Compute target features\n", - " self.target_features = self.calculate_number_features(\n", - " number_features=self.target_features, features=self.feature_list\n", - " )\n", - "\n", - " def _compute_numeric_features(self, df: pd.DataFrame):\n", - " \"\"\"Return those columns from the given dataset whose data type is numeric.\"\"\"\n", - " return df.select_dtypes(include=self.numerics).columns.tolist()\n", - "\n", - " @staticmethod\n", - " def calculate_number_features(\n", - " number_features: Union[int, float], features: Union[pd.DataFrame, List]\n", - " ) -> int:\n", - " n_features = (\n", - " int(number_features)\n", - " if (number_features > 1)\n", - " else int(number_features * len(features))\n", - " )\n", - " return n_features\n", - "\n", - " def train_model(self):\n", - " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", - " # Selected dataset\n", - " selected_cols = self.feature_list + [self.target]\n", - " train_data = self.dataset[selected_cols]\n", - " # Numeric features\n", - " numeric_features = self._compute_numeric_features(\n", - " df=train_data.drop(columns=[self.target])\n", - " )\n", - " self.setup_kwargs[\"numeric_features\"] = numeric_features\n", - " # Ignore features\n", - " self.setup_kwargs[\"ignore_features\"] = self.ignore_features\n", - " # Initialize pycaret setup\n", - " run_pycaret_setup(train_data=train_data, target=self.target, **self.setup_kwargs)\n", - " # Get train dataset and best models\n", - " self.x_train = get_config(\"X_train\")\n", - " # Compare models\n", - " compare_dict = (\n", - " {\"exclude\": self.exclude} if self.include is None else {\"include\": self.include}\n", - " )\n", - " self.top_models = compare_models(\n", - " n_select=self.number_models,\n", - " sort=self.sort,\n", - " **compare_dict,\n", - " verbose=False,\n", - " )\n", - "\n", - " def create_dict_models(self):\n", - " \"\"\"Create a dictionary whose values are pycaret standard models.\"\"\"\n", - " self.dict_models = {\n", - " str(top_model).split(\"(\")[0]: top_model for top_model in self.top_models\n", - " }\n", - " # Remove bad catboost key\n", - " oldkey = [key for key in self.dict_models.keys() if key.startswith(\" self.target_features:\n", - " # Call iteration\n", - " self.create_feature_list()\n", - " self.number_features = (\n", - " int(self.number_features / self.feature_division)\n", - " if self.number_features > 1\n", - " else self.number_features\n", - " )\n", - " if len(self.feature_list) <= 1:\n", - " break\n", - " return self.feature_list\n" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1198,28 +802,17 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 270, "id": "5795f3e4-652c-4a26-8c5b-f92ae325e794", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['a', 'b']" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "data.columns.tolist()" + "data = predictions.iloc[:500, np.random.randint(0,2000,size=150).tolist()]" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 284, "id": "cfb1a01d-bad0-474b-98b8-5f168fc7f9df", "metadata": {}, "outputs": [ @@ -1661,13 +1254,13 @@ " \"MCC\": 0.1,\n", " }\n", " \n", + " #opt_kwargs = param.Dict({})\n", " # 1st param layer \n", " target = param.String(default='goals_2.5')\n", " # 2nd param layer \n", " ## Feature selection parameters \n", - " number_features = param.Number(0.5, bounds=(0, None), inclusive_bounds=(False, True) )\n", + " number_features = param.Number(0.5, bounds=(0, 1), inclusive_bounds=(False, False) )\n", " target_features = param.Number(0.3, bounds=(0, None), inclusive_bounds=(False, True) )\n", - " feature_division = param.Number(3, bounds=(1, 100) )\n", " ## Metric parameters\n", " acu = param.Number(0.6, bounds=(0, 1), label='Accuracy')\n", " auc = param.Number(0.6, bounds=(0, 1), label='AUC')\n", @@ -1678,63 +1271,76 @@ " mcc = param.Number(0.1, bounds=(0, 1), label='MCC')\n", " ## Model setup and model optimization parameters\n", " ignore_features = param.ListSelector(default=None, objects=[1, 2], allow_None=True )\n", - " include = param.ListSelector(default=None, objects=_available_models + [None], allow_None=True )\n", - " sort = param.ListSelector(default=[\"AUC\"], objects=_filter_metric.keys() )\n", + " sort = param.ObjectSelector(default=\"AUC\", objects=_filter_metric.keys() )\n", + " include = param.ListSelector(default=None, objects= [None] + _available_models, allow_None=True )\n", " number_models = param.Integer(10, bounds=(2, len(_available_models)) )\n", " optimize = param.Boolean(False, label='Tuning process', doc='Call tuning process during feature evaluation.')\n", + " opt_list = param.ListSelector(default=['AUC'], objects=list(_filter_metric.keys())[:-2], precedence=-1, label='Tuning list')\n", " # Hidden layers\n", " dataset = param.ClassSelector(class_=pd.DataFrame, precedence=-1)\n", - " metric_dict = param.Dict(default=_filter_metric, precedence=-1)\n", - " start_run = None#param.Number(bounds=(0,None))\n", + " filter_metrics = param.Dict(default=_filter_metric, precedence=-1)\n", " \n", " def __init__(self, dataset, **kwargs):\n", " upper_bound = dataset.shape[1]\n", - " self.param.number_features.bounds = (0, upper_bound)\n", " self.param.target_features.bounds = (0, upper_bound)\n", - " self.param.ignore_features.objects = dataset.columns.to_list() + [None]\n", + " self.param.ignore_features.objects = [None] + dataset.columns.to_list()\n", + " self.param.target.default = dataset.columns.tolist()[-1]\n", " super(Widget, self).__init__(dataset=dataset, **kwargs)\n", + " self.button = pn.widgets.Button(name='Start process!', button_type=\"success\") \n", + " self.button.on_click(self.run_process)\n", " \n", + " @param.depends('optimize', watch=True)\n", + " def update_precedence(self):\n", + " self.param.opt_list.precedence = 1 if self.optimize else -1\n", + " \n", " @param.depends(\"acu\", \"auc\", \"rec\", \"pre\", \"f1\", \"kappa\", \"mcc\", watch=True)\n", - " def _define_metric_dict(self):\n", + " def _define_filter_metrics(self):\n", " legend = [\"acu\", \"auc\", \"rec\", \"pre\", \"f1\", \"kappa\", \"mcc\"]\n", - " self.metric_dict = {key: getattr(self, key) for key in legend} \n", - " \n", - " @staticmethod\n", - " def _button():\n", - " return pn.widgets.Button(name='Start process!', button_type=\"success\") \n", + " self.filter_metrics = {key: getattr(self, key) for key in legend} \n", + " \n", + " \n", + " def _discrete(self):\n", + " options = np.linspace(0,1,100,endpoint=False)[1:].tolist() + np.linspace(1,self.dataset.shape[1],200, dtype=int).tolist()\n", + " return {'widget_type': pn.widgets.DiscreteSlider,\n", + " 'name': 'Target features', \n", + " 'options': options, \n", + " 'value': 0.3,\n", + " 'width': 280}\n", + "\n", " \n", " def interactive_panel(self):\n", - " first_col = ['target', 'number_features', 'target_features', 'feature_division', 'ignore_features', 'sort']\n", - " second_col = ['include', 'number_models', 'optimize', 'acu', 'auc', 'rec', 'pre', 'f1', 'kappa', 'mcc']\n", - " button = self._button()\n", - " self.start_run = button.clicks\n", + " first_col = ['target', 'number_features', 'target_features', 'ignore_features', 'sort', 'include', 'number_models']\n", + " second_col = ['acu', 'auc', 'rec', 'pre', 'f1', 'kappa', 'mcc', 'optimize', 'opt_list']\n", " view = pn.Row(\n", " pn.Column(\n", " pn.panel(self.param,\n", " parameters=[c for c in first_col],\n", - " name='Feature parameters')\n", + " name='Feature parameters and models included',\n", + " widgets={'target_features': self._discrete()}\n", + " )\n", " ),\n", " pn.Column(\n", " pn.panel(self.param,\n", " parameters=[c for c in second_col],\n", - " name='Models included and metric parameters')\n", + " name='Metric and optimize parameters')\n", " ),\n", " pn.Column(\n", - " pn.panel(button, name=\"Run the library to select relevant features\")\n", + " pn.panel(self.button, name=\"Run the library to select relevant features\")\n", " ),\n", - " pn.Column(self._cosa)\n", " )\n", " return view\n", " \n", - " @param.depends(\"start_run\")\n", - " def _cosa(self):\n", - " self.target = 'goals_4.5' if self.start_run > 4 else 'miau'\n", - " #time.sleep(1)" + " def cosita(self):\n", + " return range(10, **self.opt_kwargs)\n", + "\n", + " def run_process(self):\n", + " inst = FeatureSelection(dataset = self.dataset, target=self.target, number_features=self.nu)\n", + " " ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 285, "id": "14ad638b-b851-4d51-b909-2c2fd909dd75", "metadata": { "scrolled": false @@ -1749,18 +1355,18 @@ "data": { "application/vnd.holoviews_exec.v0+json": "", "text/html": [ - "
\n", + "
\n", "\n", "\n", "\n", "\n", "\n", - "
\n", + "
\n", "
\n", "" + ], + "text/plain": [ + "FloatSlider(name='Number features', value=0.5)" + ] + }, + "execution_count": 62, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "1234" + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "pn.panel(a.param.number_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "3cbb4bfe", + "metadata": {}, + "outputs": [ + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "DiscreteSlider(formatter='%d', name='Discrete Slider', options=[2, 4, 8, 16, ...], value=32)" + ] + }, + "execution_count": 54, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "1225" + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "pn.widgets.DiscreteSlider(name='Discrete Slider', options=[2, 4, 8, 16, 32, 64, 128], value=32, tooltips=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "acf267b1", + "metadata": {}, + "outputs": [], + "source": [ + "class mem: \n", + " def __init__(self):\n", + " self.button = pn.widgets.Button(name='Click me', button_type='primary')\n", + " self.text = pn.widgets.TextInput(value='Ready')\n", + " self.button.on_click(self.b)\n", + " \n", + " def b(self, event):\n", + " self.text.value = 'Clicked {0} times'.format(self.button.clicks)\n", + " \n", + " def view(self):\n", + " return pn.Row(self.button, self.text)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "78d9264c", + "metadata": {}, + "outputs": [], + "source": [ + "cosita = mem()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9e226490", + "metadata": {}, + "outputs": [ + { + "data": {}, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\n", + "" + ], + "text/plain": [ + "Row\n", + " [0] Button(button_type='primary', name='Click me')\n", + " [1] TextInput(value='Ready')" + ] + }, + "execution_count": 11, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "1043" + } + }, + "output_type": "execute_result" + } + ], + "source": [ + "cosita.view()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "d1dbb192", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cosita.button.clicks" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b248cf01-fa47-466f-8f45-4b43cac3aa94", + "metadata": {}, + "outputs": [ + { + "data": {}, + "metadata": {}, + "output_type": "display_data" }, { "data": { @@ -2046,32 +2109,1044 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 28, + "id": "26ee5d57", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(range(1,a.dataset.shape[1]))[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 30, "id": "bc36256d-2cfd-48b6-a47c-2ffc1d9b1a1f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "['feature_performance.ipynb',\n", - " 'Untitled.ipynb',\n", - " 'logs.log',\n", - " '.ipynb_checkpoints']" + "[0.01,\n", + " 0.02,\n", + " 0.03,\n", + " 0.04,\n", + " 0.05,\n", + " 0.06,\n", + " 0.07,\n", + " 0.08,\n", + " 0.09,\n", + " 0.1,\n", + " 0.11,\n", + " 0.12,\n", + " 0.13,\n", + " 0.14,\n", + " 0.15,\n", + " 0.16,\n", + " 0.17,\n", + " 0.18,\n", + " 0.19,\n", + " 0.2,\n", + " 0.21,\n", + " 0.22,\n", + " 0.23,\n", + " 0.24,\n", + " 0.25,\n", + " 0.26,\n", + " 0.27,\n", + " 0.28,\n", + " 0.29,\n", + " 0.3,\n", + " 0.31,\n", + " 0.32,\n", + " 0.33,\n", + " 0.34,\n", + " 0.35000000000000003,\n", + " 0.36,\n", + " 0.37,\n", + " 0.38,\n", + " 0.39,\n", + " 0.4,\n", + " 0.41000000000000003,\n", + " 0.42,\n", + " 0.43,\n", + " 0.44,\n", + " 0.45,\n", + " 0.46,\n", + " 0.47000000000000003,\n", + " 0.48,\n", + " 0.49,\n", + " 0.5,\n", + " 0.51,\n", + " 0.52,\n", + " 0.53,\n", + " 0.54,\n", + " 0.55,\n", + " 0.56,\n", + " 0.5700000000000001,\n", + " 0.58,\n", + " 0.59,\n", + " 0.6,\n", + " 0.61,\n", + " 0.62,\n", + " 0.63,\n", + " 0.64,\n", + " 0.65,\n", + " 0.66,\n", + " 0.67,\n", + " 0.68,\n", + " 0.6900000000000001,\n", + " 0.7000000000000001,\n", + " 0.71,\n", + " 0.72,\n", + " 0.73,\n", + " 0.74,\n", + " 0.75,\n", + " 0.76,\n", + " 0.77,\n", + " 0.78,\n", + " 0.79,\n", + " 0.8,\n", + " 0.81,\n", + " 0.8200000000000001,\n", + " 0.8300000000000001,\n", + " 0.84,\n", + " 0.85,\n", + " 0.86,\n", + " 0.87,\n", + " 0.88,\n", + " 0.89,\n", + " 0.9,\n", + " 0.91,\n", + " 0.92,\n", + " 0.93,\n", + " 0.9400000000000001,\n", + " 0.9500000000000001,\n", + " 0.96,\n", + " 0.97,\n", + " 0.98,\n", + " 0.99,\n", + " 1,\n", + " 2,\n", + " 3,\n", + " 4,\n", + " 5,\n", + " 6,\n", + " 7,\n", + " 8,\n", + " 9,\n", + " 10,\n", + " 11,\n", + " 12,\n", + " 13,\n", + " 14,\n", + " 15,\n", + " 16,\n", + " 17,\n", + " 18,\n", + " 19,\n", + " 20,\n", + " 21,\n", + " 22,\n", + " 23,\n", + " 24,\n", + " 25,\n", + " 26,\n", + " 27,\n", + " 28,\n", + " 29,\n", + " 30,\n", + " 31,\n", + " 32,\n", + " 33,\n", + " 34,\n", + " 35,\n", + " 36,\n", + " 37,\n", + " 38,\n", + " 39,\n", + " 40,\n", + " 41,\n", + " 42,\n", + " 43,\n", + " 44,\n", + " 45,\n", + " 46,\n", + " 47,\n", + " 48,\n", + " 49,\n", + " 50,\n", + " 51,\n", + " 52,\n", + " 53,\n", + " 54,\n", + " 55,\n", + " 56,\n", + " 57,\n", + " 58,\n", + " 59,\n", + " 60,\n", + " 61,\n", + " 62,\n", + " 63,\n", + " 64,\n", + " 65,\n", + " 66,\n", + " 67,\n", + " 68,\n", + " 69,\n", + " 70,\n", + " 71,\n", + " 72,\n", + " 73,\n", + " 74,\n", + " 75,\n", + " 76,\n", + " 77,\n", + " 78,\n", + " 79,\n", + " 80,\n", + " 81,\n", + " 82,\n", + " 83,\n", + " 84,\n", + " 85,\n", + " 86,\n", + " 87,\n", + " 88,\n", + " 89,\n", + " 90,\n", + " 91,\n", + " 92,\n", + " 93,\n", + " 94,\n", + " 95,\n", + " 96,\n", + " 97,\n", + " 98,\n", + " 99,\n", + " 100,\n", + " 101,\n", + " 102,\n", + " 103,\n", + " 104,\n", + " 105,\n", + " 106,\n", + " 107,\n", + " 108,\n", + " 109,\n", + " 110,\n", + " 111,\n", + " 112,\n", + " 113,\n", + " 114,\n", + " 115,\n", + " 116,\n", + " 117,\n", + " 118,\n", + " 119,\n", + " 120,\n", + " 121,\n", + " 122,\n", + " 123,\n", + " 124,\n", + " 125,\n", + " 126,\n", + " 127,\n", + " 128,\n", + " 129,\n", + " 130,\n", + " 131,\n", + " 132,\n", + " 133,\n", + " 134,\n", + " 135,\n", + " 136,\n", + " 137,\n", + " 138,\n", + " 139,\n", + " 140,\n", + " 141,\n", + " 142,\n", + " 143,\n", + " 144,\n", + " 145,\n", + " 146,\n", + " 147,\n", + " 148,\n", + " 149,\n", + " 150,\n", + " 151,\n", + " 152,\n", + " 153,\n", + " 154,\n", + " 155,\n", + " 156,\n", + " 157,\n", + " 158,\n", + " 159,\n", + " 160,\n", + " 161,\n", + " 162,\n", + " 163,\n", + " 164,\n", + " 165,\n", + " 166,\n", + " 167,\n", + " 168,\n", + " 169,\n", + " 170,\n", + " 171,\n", + " 172,\n", + " 173,\n", + " 174,\n", + " 175,\n", + " 176,\n", + " 177,\n", + " 178,\n", + " 179,\n", + " 180,\n", + " 181,\n", + " 182,\n", + " 183,\n", + " 184,\n", + " 185,\n", + " 186,\n", + " 187,\n", + " 188,\n", + " 189,\n", + " 190,\n", + " 191,\n", + " 192,\n", + " 193,\n", + " 194,\n", + " 195,\n", + " 196,\n", + " 197,\n", + " 198,\n", + " 199,\n", + " 200,\n", + " 201,\n", + " 202,\n", + " 203,\n", + " 204,\n", + " 205,\n", + " 206,\n", + " 207,\n", + " 208,\n", + " 209,\n", + " 210,\n", + " 211,\n", + " 212,\n", + " 213,\n", + " 214,\n", + " 215,\n", + " 216,\n", + " 217,\n", + " 218,\n", + " 219,\n", + " 220,\n", + " 221,\n", + " 222,\n", + " 223,\n", + " 224,\n", + " 225,\n", + " 226,\n", + " 227,\n", + " 228,\n", + " 229,\n", + " 230,\n", + " 231,\n", + " 232,\n", + " 233,\n", + " 234,\n", + " 235,\n", + " 236,\n", + " 237,\n", + " 238,\n", + " 239,\n", + " 240,\n", + " 241,\n", + " 242,\n", + " 243,\n", + " 244,\n", + " 245,\n", + " 246,\n", + " 247,\n", + " 248,\n", + " 249,\n", + " 250,\n", + " 251,\n", + " 252,\n", + " 253,\n", + " 254,\n", + " 255,\n", + " 256,\n", + " 257,\n", + " 258,\n", + " 259,\n", + " 260,\n", + " 261,\n", + " 262,\n", + " 263,\n", + " 264,\n", + " 265,\n", + " 266,\n", + " 267,\n", + " 268,\n", + " 269,\n", + " 270,\n", + " 271,\n", + " 272,\n", + " 273,\n", + " 274,\n", + " 275,\n", + " 276,\n", + " 277,\n", + " 278,\n", + " 279,\n", + " 280,\n", + " 281,\n", + " 282,\n", + " 283,\n", + " 284,\n", + " 285,\n", + " 286,\n", + " 287,\n", + " 288,\n", + " 289,\n", + " 290,\n", + " 291,\n", + " 292,\n", + " 293,\n", + " 294,\n", + " 295,\n", + " 296,\n", + " 297,\n", + " 298,\n", + " 299,\n", + " 300,\n", + " 301,\n", + " 302,\n", + " 303,\n", + " 304,\n", + " 305,\n", + " 306,\n", + " 307,\n", + " 308,\n", + " 309,\n", + " 310,\n", + " 311,\n", + " 312,\n", + " 313,\n", + " 314,\n", + " 315,\n", + " 316,\n", + " 317,\n", + " 318,\n", + " 319,\n", + " 320,\n", + " 321,\n", + " 322,\n", + " 323,\n", + " 324,\n", + " 325,\n", + " 326,\n", + " 327,\n", + " 328,\n", + " 329,\n", + " 330,\n", + " 331,\n", + " 332,\n", + " 333,\n", + " 334,\n", + " 335,\n", + " 336,\n", + " 337,\n", + " 338,\n", + " 339,\n", + " 340,\n", + " 341,\n", + " 342,\n", + " 343,\n", + " 344,\n", + " 345,\n", + " 346,\n", + " 347,\n", + " 348,\n", + " 349,\n", + " 350,\n", + " 351,\n", + " 352,\n", + " 353,\n", + " 354,\n", + " 355,\n", + " 356,\n", + " 357,\n", + " 358,\n", + " 359,\n", + " 360,\n", + " 361,\n", + " 362,\n", + " 363,\n", + " 364,\n", + " 365,\n", + " 366,\n", + " 367,\n", + " 368,\n", + " 369,\n", + " 370,\n", + " 371,\n", + " 372,\n", + " 373,\n", + " 374,\n", + " 375,\n", + " 376,\n", + " 377,\n", + " 378,\n", + " 379,\n", + " 380,\n", + " 381,\n", + " 382,\n", + " 383,\n", + " 384,\n", + " 385,\n", + " 386,\n", + " 387,\n", + " 388,\n", + " 389,\n", + " 390,\n", + " 391,\n", + " 392,\n", + " 393,\n", + " 394,\n", + " 395,\n", + " 396,\n", + " 397,\n", + " 398,\n", + " 399,\n", + " 400,\n", + " 401,\n", + " 402,\n", + " 403,\n", + " 404,\n", + " 405,\n", + " 406,\n", + " 407,\n", + " 408,\n", + " 409,\n", + " 410,\n", + " 411,\n", + " 412,\n", + " 413,\n", + " 414,\n", + " 415,\n", + " 416,\n", + " 417,\n", + " 418,\n", + " 419,\n", + " 420,\n", + " 421,\n", + " 422,\n", + " 423,\n", + " 424,\n", + " 425,\n", + " 426,\n", + " 427,\n", + " 428,\n", + " 429,\n", + " 430,\n", + " 431,\n", + " 432,\n", + " 433,\n", + " 434,\n", + " 435,\n", + " 436,\n", + " 437,\n", + " 438,\n", + " 439,\n", + " 440,\n", + " 441,\n", + " 442,\n", + " 443,\n", + " 444,\n", + " 445,\n", + " 446,\n", + " 447,\n", + " 448,\n", + " 449,\n", + " 450,\n", + " 451,\n", + " 452,\n", + " 453,\n", + " 454,\n", + " 455,\n", + " 456,\n", + " 457,\n", + " 458,\n", + " 459,\n", + " 460,\n", + " 461,\n", + " 462,\n", + " 463,\n", + " 464,\n", + " 465,\n", + " 466,\n", + " 467,\n", + " 468,\n", + " 469,\n", + " 470,\n", + " 471,\n", + " 472,\n", + " 473,\n", + " 474,\n", + " 475,\n", + " 476,\n", + " 477,\n", + " 478,\n", + " 479,\n", + " 480,\n", + " 481,\n", + " 482,\n", + " 483,\n", + " 484,\n", + " 485,\n", + " 486,\n", + " 487,\n", + " 488,\n", + " 489,\n", + " 490,\n", + " 491,\n", + " 492,\n", + " 493,\n", + " 494,\n", + " 495,\n", + " 496,\n", + " 497,\n", + " 498,\n", + " 499,\n", + " 500,\n", + " 501,\n", + " 502,\n", + " 503,\n", + " 504,\n", + " 505,\n", + " 506,\n", + " 507,\n", + " 508,\n", + " 509,\n", + " 510,\n", + " 511,\n", + " 512,\n", + " 513,\n", + " 514,\n", + " 515,\n", + " 516,\n", + " 517,\n", + " 518,\n", + " 519,\n", + " 520,\n", + " 521,\n", + " 522,\n", + " 523,\n", + " 524,\n", + " 525,\n", + " 526,\n", + " 527,\n", + " 528,\n", + " 529,\n", + " 530,\n", + " 531,\n", + " 532,\n", + " 533,\n", + " 534,\n", + " 535,\n", + " 536,\n", + " 537,\n", + " 538,\n", + " 539,\n", + " 540,\n", + " 541,\n", + " 542,\n", + " 543,\n", + " 544,\n", + " 545,\n", + " 546,\n", + " 547,\n", + " 548,\n", + " 549,\n", + " 550,\n", + " 551,\n", + " 552,\n", + " 553,\n", + " 554,\n", + " 555,\n", + " 556,\n", + " 557,\n", + " 558,\n", + " 559,\n", + " 560,\n", + " 561,\n", + " 562,\n", + " 563,\n", + " 564,\n", + " 565,\n", + " 566,\n", + " 567,\n", + " 568,\n", + " 569,\n", + " 570,\n", + " 571,\n", + " 572,\n", + " 573,\n", + " 574,\n", + " 575,\n", + " 576,\n", + " 577,\n", + " 578,\n", + " 579,\n", + " 580,\n", + " 581,\n", + " 582,\n", + " 583,\n", + " 584,\n", + " 585,\n", + " 586,\n", + " 587,\n", + " 588,\n", + " 589,\n", + " 590,\n", + " 591,\n", + " 592,\n", + " 593,\n", + " 594,\n", + " 595,\n", + " 596,\n", + " 597,\n", + " 598,\n", + " 599,\n", + " 600,\n", + " 601,\n", + " 602,\n", + " 603,\n", + " 604,\n", + " 605,\n", + " 606,\n", + " 607,\n", + " 608,\n", + " 609,\n", + " 610,\n", + " 611,\n", + " 612,\n", + " 613,\n", + " 614,\n", + " 615,\n", + " 616,\n", + " 617,\n", + " 618,\n", + " 619,\n", + " 620,\n", + " 621,\n", + " 622,\n", + " 623,\n", + " 624,\n", + " 625,\n", + " 626,\n", + " 627,\n", + " 628,\n", + " 629,\n", + " 630,\n", + " 631,\n", + " 632,\n", + " 633,\n", + " 634,\n", + " 635,\n", + " 636,\n", + " 637,\n", + " 638,\n", + " 639,\n", + " 640,\n", + " 641,\n", + " 642,\n", + " 643,\n", + " 644,\n", + " 645,\n", + " 646,\n", + " 647,\n", + " 648,\n", + " 649,\n", + " 650,\n", + " 651,\n", + " 652,\n", + " 653,\n", + " 654,\n", + " 655,\n", + " 656,\n", + " 657,\n", + " 658,\n", + " 659,\n", + " 660,\n", + " 661,\n", + " 662,\n", + " 663,\n", + " 664,\n", + " 665,\n", + " 666,\n", + " 667,\n", + " 668,\n", + " 669,\n", + " 670,\n", + " 671,\n", + " 672,\n", + " 673,\n", + " 674,\n", + " 675,\n", + " 676,\n", + " 677,\n", + " 678,\n", + " 679,\n", + " 680,\n", + " 681,\n", + " 682,\n", + " 683,\n", + " 684,\n", + " 685,\n", + " 686,\n", + " 687,\n", + " 688,\n", + " 689,\n", + " 690,\n", + " 691,\n", + " 692,\n", + " 693,\n", + " 694,\n", + " 695,\n", + " 696,\n", + " 697,\n", + " 698,\n", + " 699,\n", + " 700,\n", + " 701,\n", + " 702,\n", + " 703,\n", + " 704,\n", + " 705,\n", + " 706,\n", + " 707,\n", + " 708,\n", + " 709,\n", + " 710,\n", + " 711,\n", + " 712,\n", + " 713,\n", + " 714,\n", + " 715,\n", + " 716,\n", + " 717,\n", + " 718,\n", + " 719,\n", + " 720,\n", + " 721,\n", + " 722,\n", + " 723,\n", + " 724,\n", + " 725,\n", + " 726,\n", + " 727,\n", + " 728,\n", + " 729,\n", + " 730,\n", + " 731,\n", + " 732,\n", + " 733,\n", + " 734,\n", + " 735,\n", + " 736,\n", + " 737,\n", + " 738,\n", + " 739,\n", + " 740,\n", + " 741,\n", + " 742,\n", + " 743,\n", + " 744,\n", + " 745,\n", + " 746,\n", + " 747,\n", + " 748,\n", + " 749,\n", + " 750,\n", + " 751,\n", + " 752,\n", + " 753,\n", + " 754,\n", + " 755,\n", + " 756,\n", + " 757,\n", + " 758,\n", + " 759,\n", + " 760,\n", + " 761,\n", + " 762,\n", + " 763,\n", + " 764,\n", + " 765,\n", + " 766,\n", + " 767,\n", + " 768,\n", + " 769,\n", + " 770,\n", + " 771,\n", + " 772,\n", + " 773,\n", + " 774,\n", + " 775,\n", + " 776,\n", + " 777,\n", + " 778,\n", + " 779,\n", + " 780,\n", + " 781,\n", + " 782,\n", + " 783,\n", + " 784,\n", + " 785,\n", + " 786,\n", + " 787,\n", + " 788,\n", + " 789,\n", + " 790,\n", + " 791,\n", + " 792,\n", + " 793,\n", + " 794,\n", + " 795,\n", + " 796,\n", + " 797,\n", + " 798,\n", + " 799,\n", + " 800,\n", + " 801,\n", + " 802,\n", + " 803,\n", + " 804,\n", + " 805,\n", + " 806,\n", + " 807,\n", + " 808,\n", + " 809,\n", + " 810,\n", + " 811,\n", + " 812,\n", + " 813,\n", + " 814,\n", + " 815,\n", + " 816,\n", + " 817,\n", + " 818,\n", + " 819,\n", + " 820,\n", + " 821,\n", + " 822,\n", + " 823,\n", + " 824,\n", + " 825,\n", + " 826,\n", + " 827,\n", + " 828,\n", + " 829,\n", + " 830,\n", + " 831,\n", + " 832,\n", + " 833,\n", + " 834,\n", + " 835,\n", + " 836,\n", + " 837,\n", + " 838,\n", + " 839,\n", + " 840,\n", + " 841,\n", + " 842,\n", + " 843,\n", + " 844,\n", + " 845,\n", + " 846,\n", + " 847,\n", + " 848,\n", + " 849,\n", + " 850,\n", + " 851,\n", + " 852,\n", + " 853,\n", + " 854,\n", + " 855,\n", + " 856,\n", + " 857,\n", + " 858,\n", + " 859,\n", + " 860,\n", + " 861,\n", + " 862,\n", + " 863,\n", + " 864,\n", + " 865,\n", + " 866,\n", + " 867,\n", + " 868,\n", + " 869,\n", + " 870,\n", + " 871,\n", + " 872,\n", + " 873,\n", + " 874,\n", + " 875,\n", + " 876,\n", + " 877,\n", + " 878,\n", + " 879,\n", + " 880,\n", + " 881,\n", + " 882,\n", + " 883,\n", + " 884,\n", + " 885,\n", + " 886,\n", + " 887,\n", + " 888,\n", + " 889,\n", + " 890,\n", + " 891,\n", + " 892,\n", + " 893,\n", + " 894,\n", + " 895,\n", + " 896,\n", + " 897,\n", + " 898,\n", + " 899,\n", + " 900,\n", + " 901,\n", + " ...]" ] }, - "execution_count": 35, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "from pathlib import Path\n", - "import os \n", - "\n", - "path = !pwd\n", - "path = Path(path[0])\n", - "path.parent\n", - "os.listdir(path)" + "np.linspace(0,1,100,endpoint=False)[1:].tolist() + list(range(1,a.dataset.shape[1]))" ] }, { diff --git a/notebooks/feat_sel_test_j1.ipynb b/notebooks/feat_sel_test_j1.ipynb new file mode 100644 index 0000000..b9ed794 --- /dev/null +++ b/notebooks/feat_sel_test_j1.ipynb @@ -0,0 +1,3908 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import product\n", + "from typing import Dict, List, Optional, Union\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import param\n", + "from pycaret.classification import (\n", + " compare_models,\n", + " create_model,\n", + " get_config,\n", + " predict_model,\n", + " setup,\n", + " tune_model,\n", + ")\n", + "from pycaret.utils import check_metric\n", + "\n", + "from feature_selection.run_pycaret_setup import run_pycaret_setup\n", + "\n", + "\n", + "class FeatureSelection(param.Parameterized):\n", + "\n", + " # Class attributes\n", + " model_class_to_name = {\n", + " \"RidgeClassifier\": \"ridge\",\n", + " \"LogisticRegression\": \"lr\",\n", + " \"LinearDiscriminantAnalysis\": \"lda\",\n", + " \"GradientBoostingClassifier\": \"gbc\",\n", + " \"QuadraticDiscriminantAnalysis\": \"qda\",\n", + " \"LGBMClassifier\": \"lightgbm\",\n", + " \"AdaBoostClassifier\": \"ada\",\n", + " \"RandomForestClassifier\": \"rf\",\n", + " \"ExtraTreesClassifier\": \"et\",\n", + " \"GaussianNB\": \"nb\",\n", + " \"DecisionTreeClassifier\": \"dt\",\n", + " \"KNeighborsClassifier\": \"knn\",\n", + " \"SGDClassifier\": \"svm\",\n", + " \"CatBoostClassifier\": \"catboost\",\n", + " \"SVC\": \"rbfsvm\",\n", + " \"GaussianProcessClassifier\": \"gpc\",\n", + " \"MLPClassifier\": \"mlp\",\n", + " \"XGBClassifier\": \"xgboost\",\n", + " }\n", + "\n", + " metrics_list = [\"Accuracy\", \"AUC\", \"Recall\", \"Precision\", \"F1\", \"Kappa\", \"MCC\"]\n", + "\n", + " # Private class attributes\n", + " _filter_metric = {\n", + " \"Accuracy\": 0.5,\n", + " \"AUC\": 0.5,\n", + " \"Recall\": 0.6,\n", + " \"Precision\": 0.6,\n", + " \"F1\": 0.6,\n", + " \"Kappa\": 0.1,\n", + " \"MCC\": 0.1,\n", + " }\n", + "\n", + " _setup_kwargs = dict(\n", + " preprocess=True,\n", + " train_size=0.75,\n", + " # test_data=test_data,\n", + " session_id=123,\n", + " normalize=True,\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.4,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " ignore_features=None,\n", + " fold_strategy=\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=4,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.4,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"kernel\",\n", + " pca_components=30,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.01,\n", + " trigonometry_features=False,\n", + " remove_outliers=False,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.01,\n", + " fix_imbalance=False,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " html=False,\n", + " )\n", + "\n", + " _numerics = [\"int16\", \"int32\", \"int64\", \"float16\", \"float32\", \"float64\", \"int\", \"float\"]\n", + "\n", + " # Init values\n", + " ## Feature selection parameters\n", + " target = param.String(\"goal_2.5\")\n", + " number_features = param.Number(\n", + " 0.5,\n", + " bounds=(0, 1),\n", + " inclusive_bounds=(False, False),\n", + " doc=\"Number of features (percentage) selected each iteration. Only the first nth \"\n", + " \"features will be kept for the next iteration.\",\n", + " )\n", + " target_features = param.Number(\n", + " 0.3,\n", + " bounds=(0, None),\n", + " inclusive_bounds=(False, True),\n", + " doc=\"Final total number of features. The goal of the package is to reduce \"\n", + " \"the incoming columns of the dataset to this 'target_features' number.\",\n", + " )\n", + " ## Metric parameters\n", + " filter_metrics = param.Dict(_filter_metric)\n", + " ## Model setup and model optimization parameters\n", + " numerics = param.List(_numerics)\n", + " ignore_features = param.List(default=[], allow_None=True)\n", + " setup_kwargs = param.Dict(_setup_kwargs)\n", + " include = param.List(default=None, item_type=str, allow_None=True)\n", + " exclude = param.List([\"qda\", \"knn\", \"nb\"], item_type=str)\n", + " sort = param.String(\"AUC\")\n", + " number_models = param.Integer(10, bounds=(2, 13))\n", + " top_models = param.List(default=None, allow_None=True)\n", + " optimize = param.Boolean(False)\n", + " opt_list = param.List([\"Accuracy\", \"Precision\", \"Recall\", \"F1\", \"AUC\"], item_type=str)\n", + " ## Class selectors\n", + " dataset = param.ClassSelector(class_=pd.DataFrame)\n", + " dict_models = param.ClassSelector(class_=dict)\n", + " tune_dict_models = param.ClassSelector(class_=dict)\n", + " x_train = param.ClassSelector(class_=pd.DataFrame)\n", + " x_df = param.DataFrame(pd.DataFrame())\n", + " model_df = param.ClassSelector(class_=pd.DataFrame)\n", + " model_tuned_df = param.ClassSelector(class_=pd.DataFrame)\n", + " features_df = param.ClassSelector(class_=pd.DataFrame)\n", + "\n", + " def __init__(self, dataset: pd.DataFrame, **kwargs):\n", + " # Copy of the incoming dataset\n", + " dataset = dataset.copy()\n", + " # Compute the upper bound of number_features, target_features, number_models\n", + " total_features = dataset.shape[1]\n", + " self.param.target_features.bounds = (0, total_features)\n", + " if \"include\" in kwargs:\n", + " self.param.number_models.default = len(kwargs[\"include\"])\n", + " self.param.number_models.bounds = (0, len(kwargs[\"include\"]))\n", + " # Call super\n", + " super(FeatureSelection, self).__init__(dataset=dataset, **kwargs)\n", + " # Get the features of the dataframe\n", + " self.feature_list = self.dataset.columns.tolist()\n", + " self.feature_list.remove(self.target) # target column should not be counted\n", + " # Compute target features\n", + " self.target_features = self.calculate_number_features(\n", + " number_features=self.target_features, features=self.feature_list\n", + " )\n", + " # Get the evaluator and the arguments. Depends on the \"include\" parameter\n", + " self._training_function, self._args = self._decide_model_eval()\n", + " # Get all the columns whose type is numeric\n", + " self.numeric_features = self._compute_numeric_features(df=self.dataset[self.feature_list])\n", + "\n", + " def _compute_numeric_features(self, df: pd.DataFrame):\n", + " \"\"\"Return those columns from the given dataset whose data type is numeric.\"\"\"\n", + " return df.select_dtypes(include=self.numerics).columns.tolist()\n", + "\n", + " def _decide_model_eval(self):\n", + " \"\"\"\n", + " Define the pycaret model evaluator depending on the number of included models.\n", + "\n", + " If the 'include' list parameter equals 1, the method will return\n", + " the 'create_models' pycaret object.\n", + " If 'include' parameter list is greatear than 1, the method will\n", + " return the 'compare_model' pycaret object and its arguments.\n", + " If 'include' parameter equals None, the method will return the\n", + " 'compare_models' pycaret object, where all possible models are\n", + " considered for evaluation, except those included within the 'exclude'\n", + " list.\n", + " \"\"\"\n", + " args = {\"n_select\": self.number_models, \"sort\": self.sort, \"verbose\": False}\n", + " training_function = compare_models\n", + " if not self.include:\n", + " args[\"exclude\"] = self.exclude\n", + " elif len(self.include) == 1:\n", + " training_function = lambda *rgs, **kwargs: [create_model(*rgs, **kwargs)]\n", + " args = {\"estimator\": self.include[0], \"verbose\": False}\n", + " else:\n", + " args[\"include\"] = self.include\n", + " return training_function, args\n", + "\n", + " @staticmethod\n", + " def calculate_number_features(\n", + " number_features: Union[int, float], features: Union[pd.DataFrame, List]\n", + " ) -> int:\n", + " n_features = (\n", + " int(number_features)\n", + " if (number_features >= 1)\n", + " else int(number_features * len(features))\n", + " )\n", + " return n_features\n", + "\n", + " def train_model(self):\n", + " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", + " # Selected dataset\n", + " selected_cols = self.feature_list + [self.target]\n", + " train_data = self.dataset[selected_cols] if self.x_df.empty else self.x_df[selected_cols]\n", + " # Numeric features\n", + " self.setup_kwargs[\"numeric_features\"] = [\n", + " c for c in self.numeric_features if c in self.feature_list\n", + " ]\n", + " # Ignore features\n", + " self.setup_kwargs[\"ignore_features\"] = [\n", + " c for c in self.ignore_features if c in self.feature_list\n", + " ]\n", + " # Initialize pycaret setup\n", + " setup(data=train_data, target=self.target, **self.setup_kwargs)\n", + " # Get train dataset and preprocessed dataframe\n", + " self.x_train = get_config(\"X_train\")\n", + " if self.x_df.empty: # TODO change x_df by dataset and add flag?\n", + " self.x_df = pd.concat([get_config(\"X\"), get_config(\"y\")], axis=1)\n", + " self.setup_kwargs[\"preprocess\"] = False # Turn off preprocessing\n", + " # Compare models\n", + " self.top_models = self._training_function(**self._args)\n", + "\n", + " def create_dict_models(self):\n", + " \"\"\"Create a dictionary whose values are pycaret standard models.\"\"\"\n", + " self.dict_models = {\n", + " str(top_model).split(\"(\")[0]: top_model for top_model in self.top_models\n", + " }\n", + " # Remove bad catboost key\n", + " oldkey = [key for key in self.dict_models.keys() if key.startswith(\" self.target_features:\n", + " # Call iteration\n", + " self.create_feature_list()\n", + " if len(self.feature_list) <= 1:\n", + " break\n", + " return self.feature_list" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import os\n", + "\n", + "from ml_bets.constants import FEATURES_PATH\n", + "from ml_bets.features.features import Features\n", + "from ml_bets.modeling.match_model import PipelineDatasets, run_pycaret_setup\n", + "\n", + "\n", + "from pycaret.utils import check_metric\n", + "from pycaret.classification import (add_metric, calibrate_model, optimize_threshold,\n", + " create_model,\n", + " finalize_model,\n", + " optimize_threshold, \n", + " save_model,\n", + " compare_models, \n", + " evaluate_model,\n", + " get_config,\n", + " setup,\n", + " tune_model,\n", + " predict_model,\n", + ")\n", + "\n", + "from ml_bets.supplementary.functions import IGNORE_FEATURES\n", + "from ml_bets.research.datasets import create_dataset\n", + "from ml_bets.features.names.goals import GOALS_FEATURES, NEW_FEATURES" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "target = \"goals_2.5\"\n", + "test_date = \"1-Dec-2021\"" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ESP1C.xls\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ING1C.xls\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ITA1C.xls\n", + "Excel file c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\MEX1C.xls is empty. Skipping\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\FRA1C.xls\n", + "Excel file c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\MLS1C.xls is empty. Skipping\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ALE1C.xls\n" + ] + } + ], + "source": [ + "feats = Features()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def patched_create_dataset(\n", + " test_date: str,\n", + " target: str,\n", + " columns=None,\n", + " odds_features: bool = True,\n", + " summary: bool = True,\n", + " odds_rankings: bool = True,\n", + " include_std: bool = True,\n", + " features: Features = None,\n", + " ignore_features=None,\n", + " drop_future_matches: bool = True,\n", + " test_weeks: int = 4,\n", + "):\n", + " features = features or Features()\n", + " examples = features.create(\n", + " columns=columns,\n", + " odds_features=odds_features,\n", + " odds_rankings=odds_rankings,\n", + " referee_features=True,\n", + " include_std=include_std,\n", + " summary=summary,\n", + " )\n", + " examples = examples[[x for x in examples.columns if \"possession\" not in x]]\n", + " if ignore_features is not None:\n", + " examples.drop(columns=ignore_features, inplace=True)\n", + " pds = PipelineDatasets(\n", + " examples=examples,\n", + " features=features,\n", + " target=target,\n", + " drop_future_matches=drop_future_matches,\n", + " test_size=test_date,\n", + " test_weeks=test_weeks,\n", + " )\n", + " return pds" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "ds = patched_create_dataset(target=target,\n", + " test_date=test_date,\n", + " features=feats,\n", + " odds_features=True,\n", + " include_std=True,\n", + " ignore_features=IGNORE_FEATURES+[\"referee\", \"hour_rank\", \"hour_before_16\", \"is_weekend\"],\n", + " drop_future_matches=False,\n", + " \n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "train_data = ds.train_data.copy()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "setup_kwargs = dict(\n", + " preprocess=True,\n", + " #custom_pipeline=loaded,\n", + " train_size=0.75,\n", + " session_id=123,\n", + " normalize=True,\n", + " # normalize_method=\"robust\",\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.8,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " #ignore_features=ignore_features,\n", + " fold_strategy=\"stratifiedkfold\",#\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=3,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.5,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"kernel\",\n", + " pca_components=50,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.05,\n", + " trigonometry_features=False,\n", + " remove_outliers=True,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.05,\n", + " fix_imbalance=True,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feature selection (without triplet)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.51580.52920.49730.52570.51110.03230.0323
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.51030.53090.49460.51990.50690.02120.0212
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52820.55430.53510.53660.53590.05610.0561
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52960.55700.52970.53850.53410.05910.0591
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "metric_param = {\n", + " \"Accuracy\": -0.1,\n", + " \"AUC\": -0.1,\n", + " \"Recall\": -0.1,\n", + " \"Precision\": -0.1,\n", + " \"F1\": -0.1,\n", + " \"Kappa\": -1.0,\n", + " \"MCC\": -1.0,\n", + " }\n", + "feat_sel = FeatureSelection(target=target,\n", + " dataset=train_data.dropna(),#[list(set(new_subset+new_feat+[target]))],\n", + " target_features=500,\n", + " filter_metrics=metric_param,\n", + " include=[\"lr\"],\n", + " setup_kwargs=setup_kwargs,\n", + " optimize=True,\n", + " opt_list=[\"AUC\"],\n", + " )\n", + "selected_features = feat_sel.repeat_pipeline()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['DEF_mean_a',\n", + " 'MED_diff',\n", + " 'accurate_cross_nocorner_std_diff',\n", + " 'accurate_cross_std_h',\n", + " 'accurate_fwd_zone_pass_mean_diff',\n", + " 'accurate_fwd_zone_pass_std_a',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_mean_h',\n", + " 'accurate_keeper_sweeper_std_a',\n", + " 'accurate_launches_mean_a',\n", + " 'accurate_layoffs_mean_a',\n", + " 'accurate_layoffs_std_a',\n", + " 'accurate_pass_std_diff',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'accurate_throws_std_diff',\n", + " 'accurate_throws_std_h',\n", + " 'att_assist_openplay_mean_a',\n", + " 'att_corner_ratio_mean_a',\n", + " 'att_freekick_goal_std_diff',\n", + " 'att_freekick_miss_mean_h',\n", + " 'att_freekick_miss_std_a',\n", + " 'att_freekick_total_mean_a',\n", + " 'att_freekick_total_mean_h',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_left_mean_diff',\n", + " 'att_goal_high_left_std_h',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_high_right_std_diff',\n", + " 'att_goal_low_centre_mean_a',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_goal_low_right_mean_diff',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_target_mean_a',\n", + " 'att_ibox_own_goal_std_h',\n", + " 'att_lf_goal_mean_diff',\n", + " 'att_lf_goal_mean_h',\n", + " 'att_lf_goal_std_h',\n", + " 'att_lg_centre_mean_a',\n", + " 'att_lg_centre_mean_diff',\n", + " 'att_lg_centre_mean_h',\n", + " 'att_miss_high_left_std_a',\n", + " 'att_miss_right_std_h',\n", + " 'att_obox_blocked_mean_h',\n", + " 'att_obox_goal_mean_h',\n", + " 'att_obox_goal_std_a',\n", + " 'att_obox_goal_std_diff',\n", + " 'att_obox_miss_mean_a',\n", + " 'att_obox_miss_mean_diff',\n", + " 'att_obox_post_mean_diff',\n", + " 'att_obx_right_mean_diff',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_openplay_mean_h',\n", + " 'att_pen_goal_mean_a',\n", + " 'att_post_left_mean_h',\n", + " 'att_post_left_std_diff',\n", + " 'attempts_conceded_ibox_std_diff',\n", + " 'attempts_conceded_obox_std_a',\n", + " 'attempts_conceded_obox_std_diff',\n", + " 'attempts_conceded_obox_std_h',\n", + " 'attempts_obox_mean_h',\n", + " 'bc_miss_div_scored_std_h',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_diff',\n", + " 'big_chance_missed_std_diff',\n", + " 'big_chance_scored_mean_diff',\n", + " 'blocked_cross_mean_a',\n", + " 'contentious_decision_mean_a',\n", + " 'contentious_decision_std_a',\n", + " 'corners_ratio_mean_diff',\n", + " 'diving_save_std_diff',\n", + " 'effective_clearance_mean_diff',\n", + " 'effective_head_clearance_mean_h',\n", + " 'first_yellow_card_std_a',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_deadball_std_diff',\n", + " 'goal_assist_deadball_std_h',\n", + " 'goal_assist_intent_norm_mean_h',\n", + " 'goal_assist_intentional_mean_h',\n", + " 'goal_assist_intentional_std_h',\n", + " 'goal_assist_mean_a',\n", + " 'goal_assist_mean_diff',\n", + " 'goal_assist_openplay_std_a',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_mean_a',\n", + " 'goal_assist_std_diff',\n", + " 'goal_assist_std_h',\n", + " 'goal_fastbreak_mean_diff',\n", + " 'goal_kicks_per_shot_mean_a',\n", + " 'goals_2t_mean_h',\n", + " 'goals_mean_diff',\n", + " 'goals_openplay_mean_a',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_diff',\n", + " 'last_man_tackle_std_a',\n", + " 'leftside_pass_mean_a',\n", + " 'long_pass_own_to_opp_success_std_diff',\n", + " 'lost_corners_mean_a',\n", + " 'no_foot_goals_ratio_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_under_goals_2.5',\n", + " 'odds_away_over_cards_4.5_h',\n", + " 'odds_away_over_cards_5.5_a',\n", + " 'odds_away_under_cards_3.5_h',\n", + " 'odds_home_under_cards_5.5_a',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'ontarget_att_assist_mean_a',\n", + " 'own_goals_std_h',\n", + " 'passes_left_mean_diff',\n", + " 'passes_right_mean_a',\n", + " 'passes_right_mean_diff',\n", + " 'passes_right_std_a',\n", + " 'passes_right_std_diff',\n", + " 'passes_right_std_h',\n", + " 'pen_goals_conceded_std_diff',\n", + " 'penalty_conceded_mean_a',\n", + " 'penalty_faced_std_diff',\n", + " 'penalty_save_std_h',\n", + " 'points_diff',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'prob_over_goals_2.5',\n", + " 'prob_squared_over_goals_4.5',\n", + " 'prob_squared_under_goals_4.5',\n", + " 'prob_under_goals_2.5',\n", + " 'ratio_over_corners_11.5_diff',\n", + " 'ratio_over_corners_9.5_diff',\n", + " 'ratio_under_corners_10.5_h',\n", + " 'ratio_under_goals_4.5_h',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'red_card_1t_std_a',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_mean_h',\n", + " 'red_card_std_a',\n", + " 'red_card_std_diff',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_std_diff',\n", + " 'saves_std_h',\n", + " 'second_yellow_mean_diff',\n", + " 'second_yellow_std_a',\n", + " 'shots_std_diff',\n", + " 'successful_final_third_passes_std_h',\n", + " 'total_bets_under_cards_4.5_a',\n", + " 'total_bets_under_corners_9.5_a',\n", + " 'total_clearance_mean_a',\n", + " 'total_expulsions_ref',\n", + " 'total_fastbreak_std_diff',\n", + " 'total_fwd_zone_pass_std_a',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_diff',\n", + " 'total_keeper_sweeper_std_diff',\n", + " 'total_launches_mean_a',\n", + " 'total_launches_std_h',\n", + " 'total_layoffs_mean_diff',\n", + " 'total_layoffs_std_diff',\n", + " 'total_red_card_match_ref',\n", + " 'total_second_yel_card_ref',\n", + " 'total_through_ball_mean_a',\n", + " 'total_through_ball_std_a',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_win_pct_over_corners_9.5_a',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_3.5_h',\n", + " 'total_yel_card_std_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_home_over_cards_6.5_a',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_cards_4.5_diff',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_std_h']" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sorted(selected_features)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### new imports " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import os\n", + "\n", + "from ml_bets.constants import FEATURES_PATH\n", + "from ml_bets.features.features import Features\n", + "from ml_bets.modeling.match_model import PipelineDatasets, run_pycaret_setup\n", + "#from featsel.feature_selection import FeatureSelection\n", + "\n", + "from pycaret.utils import check_metric\n", + "from pycaret.classification import (add_metric, calibrate_model, optimize_threshold,\n", + " create_model,\n", + " finalize_model,\n", + " optimize_threshold, \n", + " save_model,\n", + " compare_models, \n", + " evaluate_model,\n", + " get_config,\n", + " setup,\n", + " tune_model,\n", + " predict_model,\n", + ")\n", + "\n", + "from ml_bets.supplementary.functions import IGNORE_FEATURES\n", + "from ml_bets.research.datasets import create_dataset\n", + "from ml_bets.features.names.goals import GOALS_FEATURES, NEW_FEATURES" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "from ml_bets.research.tips import calibrate_tips, tips_from_model, combine_tips, predict_dataset, compose_tips, get_tip_probs" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "ix = np.logical_and(feats.matches[\"date\"].dt.month > 10,\n", + " feats.matches[\"competition\"].isin({\"mexican_primera\", 'us_major_league_soccer'}))\n", + "index = feats.matches[~ix].index" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def setup_dataset(test_date):\n", + " ds = create_dataset(target=target,\n", + " test_date=test_date,\n", + " features=feats,\n", + " odds_features=True,\n", + " include_std=True,\n", + " test_weeks=4,\n", + " ignore_features=IGNORE_FEATURES,\n", + " drop_future_matches=False,\n", + " )\n", + " train_data = ds.train_data.copy()#[ds.train_data.index.map(lambda x: \"us_major_league_soccer\" not in x and \"mexican\" not in x)]\n", + " train_data.drop(columns=[\"hour_rank\", \"hour_before_16\", \"is_weekend\"], inplace=True)\n", + " train_data = train_data[train_data.index.isin(index)][list(set(selected_features)) + [target]].copy()#.reset_index(drop=True)\n", + " test_data = ds.test_set[ds.test_set.index.isin(index)][list(set(selected_features)) + [target]].copy()#.reset_index(drop=True)\n", + " val_data = ds.val_set[ds.val_set.index.isin(index)].copy()\n", + " setup_kwargs = dict(\n", + " preprocess=True,\n", + " test_data=test_data[train_data.columns.tolist()],#.dropna(),\n", + " #numeric_features=[x for x in train_data.columns.tolist() if x != target],\n", + " #custom_pipeline=loaded,\n", + " #train_size=0.75,\n", + " session_id=123,\n", + " normalize=True,\n", + " normalize_method=\"robust\",\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.8,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " #ignore_features=ignore_features,\n", + " fold_strategy=\"stratifiedkfold\",#\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=4,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.5,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=True,\n", + " pca_method=\"kernel\",\n", + " pca_components=50,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.05,\n", + " trigonometry_features=False,\n", + " remove_outliers=True,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.05,\n", + " fix_imbalance=True,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " )\n", + " _ = setup(data=train_data, target=target, **setup_kwargs)\n", + " return train_data, test_data, val_data, ds" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "train_data, test_data, val_data, ds = setup_dataset(\"4-Dec-2021\")" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "from pycaret.classification import stack_models, ensemble_model, blend_models\n", + "def train_ensemble():\n", + " top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"et\", \"rf\", \"svm\"],\n", + " verbose=True,\n", + " )\n", + " tuned_models = [tune_model(model, optimize=\"MCC\", choose_better=True, n_iter=50, search_library=\"optuna\") for model in top_models]\n", + " cali = [calibrate_model(tuned, method=\"sigmoid\", calibrate_fold=4) for tuned in tuned_models]\n", + " blend = blend_models(cali)\n", + " opti = tune_model(blend, optimize=\"Precision\", choose_better=True, n_iter=50, search_library=\"optuna\")\n", + " return opti, cali, tuned_models" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC TT (Sec)
lrLogistic Regression0.58310.61610.59370.60300.59710.16520.16580.6300
svmSVM - Linear Kernel0.57800.00000.59750.60370.58450.15440.16560.2050
ridgeRidge Classifier0.58250.00000.59370.60180.59660.16390.16450.2000
ldaLinear Discriminant Analysis0.58190.61070.59620.60030.59720.16240.16290.2100
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"svm\"],\n", + " verbose=True,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(top_models[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feature selection (adding triplet)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(181,\n", + " 583,\n", + " ['ATT_h_mul_shots_mul_goals_mean_diff',\n", + " 'DEF_h_mul_shots_mul_goals_mean_diff',\n", + " 'DEF_mean_a',\n", + " 'DEF_mean_diff',\n", + " 'DEF_mean_h',\n", + " 'MED_a',\n", + " 'MED_diff',\n", + " 'MED_h',\n", + " 'MED_mean_a',\n", + " 'MED_mean_diff',\n", + " 'MED_mean_h',\n", + " 'MED_std_a',\n", + " 'MED_std_diff',\n", + " 'MED_std_h',\n", + " 'accurate_cross_nocorner_std_a',\n", + " 'accurate_cross_nocorner_std_diff',\n", + " 'accurate_cross_nocorner_std_h',\n", + " 'accurate_cross_std_a',\n", + " 'accurate_cross_std_diff',\n", + " 'accurate_cross_std_h',\n", + " 'accurate_fwd_zone_pass_mean_a',\n", + " 'accurate_fwd_zone_pass_mean_diff',\n", + " 'accurate_fwd_zone_pass_mean_h',\n", + " 'accurate_fwd_zone_pass_std_a',\n", + " 'accurate_fwd_zone_pass_std_diff',\n", + " 'accurate_fwd_zone_pass_std_h',\n", + " 'accurate_goal_kicks_std_a',\n", + " 'accurate_goal_kicks_std_diff',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_mean_diff',\n", + " 'accurate_keeper_sweeper_mean_h',\n", + " 'accurate_keeper_sweeper_std_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_launches_mean_a',\n", + " 'accurate_launches_mean_diff',\n", + " 'accurate_launches_mean_h',\n", + " 'accurate_layoffs_mean_a',\n", + " 'accurate_layoffs_mean_diff',\n", + " 'accurate_layoffs_mean_h',\n", + " 'accurate_layoffs_std_a',\n", + " 'accurate_layoffs_std_diff',\n", + " 'accurate_layoffs_std_h',\n", + " 'accurate_pass_std_a',\n", + " 'accurate_pass_std_diff',\n", + " 'accurate_pass_std_h',\n", + " 'accurate_through_ball_mean_a',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'accurate_through_ball_mean_h',\n", + " 'accurate_throws_std_a',\n", + " 'accurate_throws_std_diff',\n", + " 'accurate_throws_std_h',\n", + " 'att_assist_openplay_mean_a',\n", + " 'att_assist_openplay_mean_diff',\n", + " 'att_assist_openplay_mean_h',\n", + " 'att_corner_ratio_mean_a',\n", + " 'att_corner_ratio_mean_diff',\n", + " 'att_corner_ratio_mean_h',\n", + " 'att_freekick_goal_std_a',\n", + " 'att_freekick_goal_std_diff',\n", + " 'att_freekick_goal_std_h',\n", + " 'att_freekick_miss_mean_a',\n", + " 'att_freekick_miss_mean_diff',\n", + " 'att_freekick_miss_mean_h',\n", + " 'att_freekick_miss_std_a',\n", + " 'att_freekick_miss_std_diff',\n", + " 'att_freekick_miss_std_h',\n", + " 'att_freekick_total_mean_a',\n", + " 'att_freekick_total_mean_diff',\n", + " 'att_freekick_total_mean_h',\n", + " 'att_goal_high_centre_mean_a',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_mean_h',\n", + " 'att_goal_high_centre_std_a',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_centre_std_h',\n", + " 'att_goal_high_left_mean_a',\n", + " 'att_goal_high_left_mean_diff',\n", + " 'att_goal_high_left_mean_h',\n", + " 'att_goal_high_left_std_a',\n", + " 'att_goal_high_left_std_diff',\n", + " 'att_goal_high_left_std_h',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_high_right_std_diff',\n", + " 'att_goal_high_right_std_h',\n", + " 'att_goal_low_centre_mean_a',\n", + " 'att_goal_low_centre_mean_diff',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_diff',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_goal_low_right_mean_a',\n", + " 'att_goal_low_right_mean_diff',\n", + " 'att_goal_low_right_mean_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_diff',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_target_mean_diff',\n", + " 'att_hd_target_mean_h',\n", + " 'att_ibox_own_goal_std_a',\n", + " 'att_ibox_own_goal_std_diff',\n", + " 'att_ibox_own_goal_std_h',\n", + " 'att_lf_goal_mean_a',\n", + " 'att_lf_goal_mean_diff',\n", + " 'att_lf_goal_mean_h',\n", + " 'att_lf_goal_std_a',\n", + " 'att_lf_goal_std_diff',\n", + " 'att_lf_goal_std_h',\n", + " 'att_lg_centre_mean_a',\n", + " 'att_lg_centre_mean_diff',\n", + " 'att_lg_centre_mean_h',\n", + " 'att_miss_high_left_std_a',\n", + " 'att_miss_high_left_std_diff',\n", + " 'att_miss_high_left_std_h',\n", + " 'att_miss_right_std_a',\n", + " 'att_miss_right_std_diff',\n", + " 'att_miss_right_std_h',\n", + " 'att_obox_blocked_mean_a',\n", + " 'att_obox_blocked_mean_diff',\n", + " 'att_obox_blocked_mean_h',\n", + " 'att_obox_goal_mean_a',\n", + " 'att_obox_goal_mean_diff',\n", + " 'att_obox_goal_mean_h',\n", + " 'att_obox_goal_std_a',\n", + " 'att_obox_goal_std_diff',\n", + " 'att_obox_goal_std_h',\n", + " 'att_obox_miss_mean_a',\n", + " 'att_obox_miss_mean_diff',\n", + " 'att_obox_miss_mean_h',\n", + " 'att_obox_post_mean_a',\n", + " 'att_obox_post_mean_diff',\n", + " 'att_obox_post_mean_h',\n", + " 'att_obx_right_mean_a',\n", + " 'att_obx_right_mean_diff',\n", + " 'att_obx_right_mean_h',\n", + " 'att_obxd_right_mean_a',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_mean_h',\n", + " 'att_obxd_right_std_a',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_obxd_right_std_h',\n", + " 'att_openplay_mean_a',\n", + " 'att_openplay_mean_diff',\n", + " 'att_openplay_mean_h',\n", + " 'att_pen_goal_mean_a',\n", + " 'att_pen_goal_mean_diff',\n", + " 'att_pen_goal_mean_h',\n", + " 'att_post_left_mean_a',\n", + " 'att_post_left_mean_diff',\n", + " 'att_post_left_mean_h',\n", + " 'att_post_left_std_a',\n", + " 'att_post_left_std_diff',\n", + " 'att_post_left_std_h',\n", + " 'attempts_conceded_ibox_std_a',\n", + " 'attempts_conceded_ibox_std_diff',\n", + " 'attempts_conceded_ibox_std_h',\n", + " 'attempts_conceded_obox_std_a',\n", + " 'attempts_conceded_obox_std_diff',\n", + " 'attempts_conceded_obox_std_h',\n", + " 'attempts_obox_mean_a',\n", + " 'attempts_obox_mean_diff',\n", + " 'attempts_obox_mean_h',\n", + " 'bc_miss_div_scored_std_a',\n", + " 'bc_miss_div_scored_std_diff',\n", + " 'bc_miss_div_scored_std_h',\n", + " 'big_chance_created_mean_a',\n", + " 'big_chance_created_mean_diff',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_a',\n", + " 'big_chance_created_std_diff',\n", + " 'big_chance_created_std_h',\n", + " 'big_chance_missed_std_a',\n", + " 'big_chance_missed_std_diff',\n", + " 'big_chance_missed_std_h',\n", + " 'big_chance_scored_mean_a',\n", + " 'big_chance_scored_mean_diff',\n", + " 'big_chance_scored_mean_diff_mul_total_fwd_zone_pass_mean_diff',\n", + " 'big_chance_scored_mean_h',\n", + " 'blocked_cross_mean_a',\n", + " 'blocked_cross_mean_diff',\n", + " 'blocked_cross_mean_h',\n", + " 'contentious_decision_mean_a',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_mean_h',\n", + " 'contentious_decision_std_a',\n", + " 'contentious_decision_std_diff',\n", + " 'contentious_decision_std_h',\n", + " 'corner_taken_std_mul_att_corner_ratio_mean_diffs',\n", + " 'corners_ratio_mean_a',\n", + " 'corners_ratio_mean_diff',\n", + " 'corners_ratio_mean_h',\n", + " 'defender_goals_mean_a',\n", + " 'defender_goals_mean_diff',\n", + " 'defender_goals_mean_h',\n", + " 'diving_save_std_a',\n", + " 'diving_save_std_diff',\n", + " 'diving_save_std_h',\n", + " 'effective_clearance_mean_a',\n", + " 'effective_clearance_mean_diff',\n", + " 'effective_clearance_mean_h',\n", + " 'effective_head_clearance_mean_a',\n", + " 'effective_head_clearance_mean_diff',\n", + " 'effective_head_clearance_mean_h',\n", + " 'first_yellow_card_std_a',\n", + " 'first_yellow_card_std_diff',\n", + " 'first_yellow_card_std_h',\n", + " 'forward_goals_mean_a',\n", + " 'forward_goals_mean_diff',\n", + " 'forward_goals_mean_h',\n", + " 'fwd_pass_div_long_pass_own_to_opp_success_std_a',\n", + " 'fwd_pass_div_long_pass_own_to_opp_success_std_diff',\n", + " 'fwd_pass_div_long_pass_own_to_opp_success_std_h',\n", + " 'goal_assist_deadball_mean_a',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_deadball_mean_h',\n", + " 'goal_assist_deadball_std_a',\n", + " 'goal_assist_deadball_std_diff',\n", + " 'goal_assist_deadball_std_h',\n", + " 'goal_assist_intent_norm_mean_a',\n", + " 'goal_assist_intent_norm_mean_diff',\n", + " 'goal_assist_intent_norm_mean_h',\n", + " 'goal_assist_intentional_mean_a',\n", + " 'goal_assist_intentional_mean_diff',\n", + " 'goal_assist_intentional_mean_h',\n", + " 'goal_assist_intentional_std_a',\n", + " 'goal_assist_intentional_std_diff',\n", + " 'goal_assist_intentional_std_h',\n", + " 'goal_assist_mean_a',\n", + " 'goal_assist_mean_diff',\n", + " 'goal_assist_mean_h',\n", + " 'goal_assist_openplay_std_a',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_mean_a',\n", + " 'goal_assist_setplay_mean_diff',\n", + " 'goal_assist_setplay_mean_h',\n", + " 'goal_assist_std_a',\n", + " 'goal_assist_std_diff',\n", + " 'goal_assist_std_h',\n", + " 'goal_fastbreak_mean_a',\n", + " 'goal_fastbreak_mean_diff',\n", + " 'goal_fastbreak_mean_h',\n", + " 'goal_kicks_per_shot_mean_a',\n", + " 'goal_kicks_per_shot_mean_diff',\n", + " 'goal_kicks_per_shot_mean_h',\n", + " 'goals_2t_mean_a',\n", + " 'goals_2t_mean_diff',\n", + " 'goals_2t_mean_h',\n", + " 'goals_mean_a',\n", + " 'goals_mean_diff',\n", + " 'goals_mean_h',\n", + " 'goals_openplay_mean_a',\n", + " 'goals_openplay_mean_diff',\n", + " 'goals_openplay_mean_h',\n", + " 'high_to_low_goals_mean_a',\n", + " 'high_to_low_goals_mean_diff',\n", + " 'high_to_low_goals_mean_h',\n", + " 'imp_prob_over_goals_0.5_a',\n", + " 'imp_prob_over_goals_0.5_diff',\n", + " 'imp_prob_over_goals_0.5_h',\n", + " 'imp_prob_over_goals_1.5_a',\n", + " 'imp_prob_over_goals_1.5_diff',\n", + " 'imp_prob_over_goals_1.5_h',\n", + " 'imp_prob_over_goals_2.5_a',\n", + " 'imp_prob_over_goals_2.5_diff',\n", + " 'imp_prob_over_goals_2.5_h',\n", + " 'imp_prob_over_goals_3.5_a',\n", + " 'imp_prob_over_goals_3.5_diff',\n", + " 'imp_prob_over_goals_3.5_h',\n", + " 'imp_prob_over_goals_4.5_a',\n", + " 'imp_prob_over_goals_4.5_diff',\n", + " 'imp_prob_over_goals_4.5_h',\n", + " 'imp_prob_under_goals_0.5_a',\n", + " 'imp_prob_under_goals_0.5_diff',\n", + " 'imp_prob_under_goals_0.5_h',\n", + " 'imp_prob_under_goals_1.5_a',\n", + " 'imp_prob_under_goals_1.5_diff',\n", + " 'imp_prob_under_goals_1.5_h',\n", + " 'imp_prob_under_goals_2.5_a',\n", + " 'imp_prob_under_goals_2.5_diff',\n", + " 'imp_prob_under_goals_2.5_h',\n", + " 'imp_prob_under_goals_3.5_a',\n", + " 'imp_prob_under_goals_3.5_diff',\n", + " 'imp_prob_under_goals_3.5_h',\n", + " 'imp_prob_under_goals_4.5_a',\n", + " 'imp_prob_under_goals_4.5_diff',\n", + " 'imp_prob_under_goals_4.5_h',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_a',\n", + " 'last_man_tackle_mean_diff',\n", + " 'last_man_tackle_mean_h',\n", + " 'last_man_tackle_std_a',\n", + " 'last_man_tackle_std_diff',\n", + " 'last_man_tackle_std_h',\n", + " 'left_div_right_foot_goals_mean_a',\n", + " 'left_div_right_foot_goals_mean_diff',\n", + " 'left_div_right_foot_goals_mean_h',\n", + " 'leftside_pass_div_accurate_pass_std_a',\n", + " 'leftside_pass_div_accurate_pass_std_diff',\n", + " 'leftside_pass_div_accurate_pass_std_h',\n", + " 'leftside_pass_mean_a',\n", + " 'leftside_pass_mean_diff',\n", + " 'leftside_pass_mean_h',\n", + " 'long_pass_own_to_opp_success_std_a',\n", + " 'long_pass_own_to_opp_success_std_diff',\n", + " 'long_pass_own_to_opp_success_std_h',\n", + " 'lost_corners_mean_a',\n", + " 'lost_corners_mean_diff',\n", + " 'lost_corners_mean_h',\n", + " 'midfielder_goals_mean_a',\n", + " 'midfielder_goals_mean_diff',\n", + " 'midfielder_goals_mean_h',\n", + " 'no_foot_goals_ratio_mean_a',\n", + " 'no_foot_goals_ratio_mean_diff',\n", + " 'no_foot_goals_ratio_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_diff',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_over_corners_11.5',\n", + " 'odd_ratio_over_corners_9.5',\n", + " 'odd_ratio_under_corners_10.5',\n", + " 'odd_ratio_under_goals_1.5',\n", + " 'odd_ratio_under_goals_2.5',\n", + " 'odd_ratio_under_goals_3.5',\n", + " 'odd_ratio_under_goals_4.5',\n", + " 'odd_ratio_under_goals_4.5',\n", + " 'odds_away_over_cards_4.5_a',\n", + " 'odds_away_over_cards_4.5_diff',\n", + " 'odds_away_over_cards_4.5_h',\n", + " 'odds_away_over_cards_5.5_a',\n", + " 'odds_away_over_cards_5.5_diff',\n", + " 'odds_away_over_cards_5.5_h',\n", + " 'odds_away_under_cards_3.5_a',\n", + " 'odds_away_under_cards_3.5_diff',\n", + " 'odds_away_under_cards_3.5_h',\n", + " 'odds_home_under_cards_5.5_a',\n", + " 'odds_home_under_cards_5.5_diff',\n", + " 'odds_home_under_cards_5.5_h',\n", + " 'odds_home_under_goals_0.5_a',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'odds_home_under_goals_0.5_h',\n", + " 'ontarget_att_assist_mean_a',\n", + " 'ontarget_att_assist_mean_diff',\n", + " 'ontarget_att_assist_mean_h',\n", + " 'own_goals_mean_a',\n", + " 'own_goals_mean_diff',\n", + " 'own_goals_mean_h',\n", + " 'own_goals_std_a',\n", + " 'own_goals_std_diff',\n", + " 'own_goals_std_h',\n", + " 'passes_left_mean_a',\n", + " 'passes_left_mean_diff',\n", + " 'passes_left_mean_h',\n", + " 'passes_right_mean_a',\n", + " 'passes_right_mean_diff',\n", + " 'passes_right_mean_h',\n", + " 'passes_right_std_a',\n", + " 'passes_right_std_diff',\n", + " 'passes_right_std_h',\n", + " 'pen_goals_conceded_std_a',\n", + " 'pen_goals_conceded_std_diff',\n", + " 'pen_goals_conceded_std_h',\n", + " 'penalty_conceded_mean_a',\n", + " 'penalty_conceded_mean_diff',\n", + " 'penalty_conceded_mean_h',\n", + " 'penalty_faced_std_a',\n", + " 'penalty_faced_std_diff',\n", + " 'penalty_faced_std_h',\n", + " 'penalty_save_std_a',\n", + " 'penalty_save_std_diff',\n", + " 'penalty_save_std_h',\n", + " 'points_a',\n", + " 'points_diff',\n", + " 'points_h',\n", + " 'points_mean_a',\n", + " 'points_mean_diff',\n", + " 'points_mean_h',\n", + " 'points_std_a',\n", + " 'points_std_diff',\n", + " 'points_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'prob_over_goals_1.5',\n", + " 'prob_over_goals_2.5',\n", + " 'prob_over_goals_3.5',\n", + " 'prob_over_goals_4.5',\n", + " 'prob_squared_over_goals_1.5',\n", + " 'prob_squared_over_goals_2.5',\n", + " 'prob_squared_over_goals_3.5',\n", + " 'prob_squared_over_goals_4.5',\n", + " 'prob_squared_under_goals_1.5',\n", + " 'prob_squared_under_goals_2.5',\n", + " 'prob_squared_under_goals_3.5',\n", + " 'prob_squared_under_goals_4.5',\n", + " 'prob_under_goals_1.5',\n", + " 'prob_under_goals_2.5',\n", + " 'prob_under_goals_3.5',\n", + " 'prob_under_goals_4.5',\n", + " 'ratio_over_corners_11.5_a',\n", + " 'ratio_over_corners_11.5_diff',\n", + " 'ratio_over_corners_11.5_h',\n", + " 'ratio_over_corners_9.5_a',\n", + " 'ratio_over_corners_9.5_diff',\n", + " 'ratio_over_corners_9.5_h',\n", + " 'ratio_under_corners_10.5_a',\n", + " 'ratio_under_corners_10.5_diff',\n", + " 'ratio_under_corners_10.5_h',\n", + " 'ratio_under_goals_4.5_a',\n", + " 'ratio_under_goals_4.5_diff',\n", + " 'ratio_under_goals_4.5_h',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_over_goals_3.5',\n", + " 'raw_prob_over_goals_3.5',\n", + " 'raw_prob_over_goals_4.5',\n", + " 'raw_prob_over_goals_4.5',\n", + " 'raw_prob_under_goals_1.5',\n", + " 'raw_prob_under_goals_2.5',\n", + " 'raw_prob_under_goals_3.5',\n", + " 'raw_prob_under_goals_4.5',\n", + " 'red_card_1t_std_a',\n", + " 'red_card_1t_std_diff',\n", + " 'red_card_1t_std_h',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_2t_mean_diff',\n", + " 'red_card_2t_mean_h',\n", + " 'red_card_mean_a',\n", + " 'red_card_mean_diff',\n", + " 'red_card_mean_h',\n", + " 'red_card_std_a',\n", + " 'red_card_std_diff',\n", + " 'red_card_std_h',\n", + " 'rescinded_red_card_mean_a',\n", + " 'rescinded_red_card_mean_diff',\n", + " 'rescinded_red_card_mean_h',\n", + " 'rescinded_red_card_std_a',\n", + " 'rescinded_red_card_std_diff',\n", + " 'rescinded_red_card_std_h',\n", + " 'right_to_left_goals_mean_a',\n", + " 'right_to_left_goals_mean_a',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_mean_h',\n", + " 'right_to_left_goals_mean_h',\n", + " 'right_to_left_goals_std_a',\n", + " 'right_to_left_goals_std_diff',\n", + " 'right_to_left_goals_std_h',\n", + " 'rightside_pass_div_accurate_pass_std_a',\n", + " 'rightside_pass_div_accurate_pass_std_diff',\n", + " 'rightside_pass_div_accurate_pass_std_h',\n", + " 'rightside_pass_div_leftside_pass_mean_a',\n", + " 'rightside_pass_div_leftside_pass_mean_diff',\n", + " 'rightside_pass_div_leftside_pass_mean_h',\n", + " 'saves_std_a',\n", + " 'saves_std_diff',\n", + " 'saves_std_h',\n", + " 'second_yellow_mean_a',\n", + " 'second_yellow_mean_diff',\n", + " 'second_yellow_mean_h',\n", + " 'second_yellow_std_a',\n", + " 'second_yellow_std_diff',\n", + " 'second_yellow_std_h',\n", + " 'shots_div_passes_left_mean_a',\n", + " 'shots_div_passes_left_mean_diff',\n", + " 'shots_div_passes_left_mean_h',\n", + " 'shots_div_passes_right_mean_a',\n", + " 'shots_div_passes_right_mean_diff',\n", + " 'shots_div_passes_right_mean_h',\n", + " 'shots_div_passes_right_std_a',\n", + " 'shots_div_passes_right_std_diff',\n", + " 'shots_div_passes_right_std_h',\n", + " 'shots_mul_goals_mean_a',\n", + " 'shots_mul_goals_mean_diff',\n", + " 'shots_mul_goals_mean_h',\n", + " 'shots_std_a',\n", + " 'shots_std_diff',\n", + " 'shots_std_h',\n", + " 'successful_final_third_passes_std_a',\n", + " 'successful_final_third_passes_std_diff',\n", + " 'successful_final_third_passes_std_h',\n", + " 'total_bets_under_cards_4.5_a',\n", + " 'total_bets_under_cards_4.5_diff',\n", + " 'total_bets_under_cards_4.5_h',\n", + " 'total_bets_under_corners_9.5_a',\n", + " 'total_bets_under_corners_9.5_diff',\n", + " 'total_bets_under_corners_9.5_h',\n", + " 'total_clearance_mean_a',\n", + " 'total_clearance_mean_diff',\n", + " 'total_clearance_mean_h',\n", + " 'total_expulsions_ref',\n", + " 'total_fastbreak_std_a',\n", + " 'total_fastbreak_std_diff',\n", + " 'total_fastbreak_std_h',\n", + " 'total_fwd_zone_pass_div_long_pass_own_to_opp_success_std_a',\n", + " 'total_fwd_zone_pass_div_long_pass_own_to_opp_success_std_diff',\n", + " 'total_fwd_zone_pass_div_long_pass_own_to_opp_success_std_h',\n", + " 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_diff',\n", + " 'total_fwd_zone_pass_std_a',\n", + " 'total_fwd_zone_pass_std_diff',\n", + " 'total_fwd_zone_pass_std_h',\n", + " 'total_high_claim_mean_a',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_high_claim_mean_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_diff',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_keeper_sweeper_std_a',\n", + " 'total_keeper_sweeper_std_diff',\n", + " 'total_keeper_sweeper_std_h',\n", + " 'total_launches_mean_a',\n", + " 'total_launches_mean_diff',\n", + " 'total_launches_mean_h',\n", + " 'total_launches_std_a',\n", + " 'total_launches_std_diff',\n", + " 'total_launches_std_h',\n", + " 'total_layoffs_mean_a',\n", + " 'total_layoffs_mean_diff',\n", + " 'total_layoffs_mean_h',\n", + " 'total_layoffs_std_a',\n", + " 'total_layoffs_std_diff',\n", + " 'total_layoffs_std_h',\n", + " 'total_red_card_match_ref',\n", + " 'total_red_card_mean_a',\n", + " 'total_red_card_mean_diff',\n", + " 'total_red_card_mean_h',\n", + " 'total_red_card_std_a',\n", + " 'total_red_card_std_diff',\n", + " 'total_red_card_std_h',\n", + " 'total_second_yel_card_away_ref',\n", + " 'total_second_yel_card_home_ref',\n", + " 'total_second_yel_card_ref',\n", + " 'total_through_ball_mean_a',\n", + " 'total_through_ball_mean_diff',\n", + " 'total_through_ball_mean_h',\n", + " 'total_through_ball_std_a',\n", + " 'total_through_ball_std_diff',\n", + " 'total_through_ball_std_h',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_throws_std_h',\n", + " 'total_win_pct_over_corners_9.5_a',\n", + " 'total_win_pct_over_corners_9.5_diff',\n", + " 'total_win_pct_over_corners_9.5_h',\n", + " 'total_win_pct_over_goals_2.5_a',\n", + " 'total_win_pct_over_goals_2.5_diff',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_1.5_diff',\n", + " 'total_win_pct_under_goals_1.5_h',\n", + " 'total_win_pct_under_goals_3.5_a',\n", + " 'total_win_pct_under_goals_3.5_diff',\n", + " 'total_win_pct_under_goals_3.5_h',\n", + " 'total_yel_card_std_a',\n", + " 'total_yel_card_std_diff',\n", + " 'total_yel_card_std_h',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_over_goals_2.5_h',\n", + " 'win_pct_home_over_cards_6.5_a',\n", + " 'win_pct_home_over_cards_6.5_diff',\n", + " 'win_pct_home_over_cards_6.5_h',\n", + " 'win_pct_home_over_goals_2.5_a',\n", + " 'win_pct_home_over_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_cards_4.5_a',\n", + " 'win_pct_home_under_cards_4.5_diff',\n", + " 'win_pct_home_under_cards_4.5_h',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_diff',\n", + " 'won_corners_ratio_mean_diff',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_std_a',\n", + " 'won_corners_ratio_std_diff',\n", + " 'won_corners_ratio_std_h'])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "common_feat = list(set([\"_\".join(x.split(\"_\")[:-1]) for x in selected_features]))\n", + "new_subset = [x for x in train_data.columns for c in common_feat if c in x]\n", + "\n", + "len(selected_features), len(new_subset), sorted(new_subset)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Monkey patch feature_selection module.\"\"\"\n", + "from typing import List, Tuple\n", + "\n", + "# from feature_selection import FeatureSelection\n", + "\n", + "\n", + "def get_root_features(feature_list: List) -> Tuple[List, List]:\n", + " \"\"\"Get the features related to teams, i.e., those ended with \"_a\", \"_h\", \"_diff\".\"\"\"\n", + " # Conditions\n", + " cond1 = lambda x: x.endswith(\"_h\")\n", + " cond2 = lambda x: x.endswith(\"_a\")\n", + " cond3 = lambda x: x.endswith(\"_diff\")\n", + " # Features ended with _h, _a, _diff\n", + " sublist = [c for c in feature_list if (cond1(c) or cond2(c) or cond3(c))]\n", + " return sublist, list(set([\"_\".join(c.split(\"_\")[:-1]) for c in sublist]))\n", + "\n", + "\n", + "def append_list(root_features: List, og_columns: List):\n", + " \"\"\"Append suffixes to the incoming feature labels.\"\"\"\n", + " # Create empty list\n", + " dressed_list = list()\n", + " # Add suffixes to each root label\n", + " # dressed_list = [c for root in root_features for c in df_columns if c.startswith(root)]\n", + " for c in root_features:\n", + " dressed_list.append(f\"{c}_h\")\n", + " dressed_list.append(f\"{c}_a\")\n", + " dressed_list.append(f\"{c}_diff\")\n", + " dressed_list = [c for c in dressed_list if c in og_columns]\n", + " # return list(set(dressed_list))\n", + " return dressed_list\n", + "\n", + "\n", + "def massage_feat_list(feature_list: List, og_columns: List):\n", + " \"\"\"\n", + " Add team features to the incoming list.\n", + "\n", + " Given a feature list, this function adds the full trio of team\n", + " features (*_h, *_a, *_diff) to those already present that are\n", + " related to team statistics.\n", + " \"\"\"\n", + " feature_list = feature_list.copy()\n", + " # Get list of match features and root\n", + " sublist, root = get_root_features(feature_list)\n", + " # Get features not related to teams\n", + " no_team = list(set(feature_list) - set(sublist))\n", + " # Add suffixes to roots\n", + " dressed = append_list(root_features=root, og_columns=og_columns.copy())\n", + " # return list(set(no_team + dressed))\n", + " return no_team + dressed\n", + "\n", + "\n", + "def finalize_list(feature_list: List, df_columns: List):\n", + " \"\"\"\n", + " Complete the feature_list returned by the selection module.\n", + "\n", + " Once the number of features has been reduced to a subset of\n", + " relevant features, this function completes the list by adding\n", + " team features to those already present.\n", + "\n", + " If a team feature is present, but the set only contains the one\n", + " related to the home or away team, the function adds the corresponding\n", + " feature related to the difference between teams, i.e., team_feat_diff.\n", + " \"\"\"\n", + " feature_list = feature_list.copy()\n", + " # Elements with _h, _a, _diff\n", + " sublist, roots = get_root_features(feature_list)\n", + " # List to be used as building block\n", + " final_list = list(set(feature_list) - set(sublist))\n", + " # Check for team features\n", + " for root in roots:\n", + " triplet = [f\"{root}_h\", f\"{root}_a\", f\"{root}_diff\"]\n", + " subset = [c for tri in triplet for c in sublist if c == tri]\n", + " if len(subset) < 2 and not subset[0].endswith(\"_diff\"):\n", + " subset.append(f\"{root}_diff\")\n", + " final_list = final_list + subset\n", + " final_list = [c for c in final_list if c in df_columns]\n", + " return final_list\n", + "\n", + "\n", + "def patch_repeat_pipeline(self):\n", + " \"\"\"Iterate over the process to create the feature list and repeat it self.repeat times (PATCH).\"\"\"\n", + " i = 0\n", + " while len(self.feature_list) > self.target_features:\n", + " i += 1\n", + " print(f\"{i} iteration\")\n", + " # Call iteration\n", + " self.create_feature_list()\n", + " self.feature_list = massage_feat_list(\n", + " feature_list=self.feature_list, og_columns=self.x_df.columns\n", + " )\n", + " if len(self.feature_list) <= 1:\n", + " break\n", + " return finalize_list(feature_list=self.feature_list, df_columns=self.x_df.columns)\n", + "\n", + "def patch_train_model(self):\n", + " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", + " # Selected dataset\n", + " selected_cols = self.feature_list + [self.target]\n", + " train_data = self.dataset[selected_cols] if self.x_df.empty else self.x_df[selected_cols]\n", + " # Numeric features\n", + " self.setup_kwargs[\"numeric_features\"] = [\n", + " c for c in self.numeric_features if c in self.feature_list\n", + " ]\n", + " # Ignore features\n", + " self.setup_kwargs[\"ignore_features\"] = [\n", + " c for c in self.ignore_features if c in self.feature_list\n", + " ]\n", + " self.setup_kwargs[\"feature_interaction\"]: False\n", + " # Initialize pycaret setup\n", + " setup(data=train_data, target=self.target, **self.setup_kwargs)\n", + " # Get train dataset and preprocessed dataframe\n", + " self.x_train = get_config(\"X_train\")\n", + " if self.x_df.empty: # TODO change x_df by dataset and add flag?\n", + " self.x_df = pd.concat([get_config(\"X\"), get_config(\"y\")], axis=1)\n", + " self.setup_kwargs[\"preprocess\"] = False # Turn off preprocessing\n", + " # Compare models\n", + " self.top_models = self._training_function(**self._args)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:param: Setting non-Parameter class attribute FeatureSelection.train_model = \n" + ] + } + ], + "source": [ + "FeatureSelection.train_model = patch_train_model" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:param: Setting non-Parameter class attribute FeatureSelection.repeat_pipeline = \n" + ] + } + ], + "source": [ + "FeatureSelection.repeat_pipeline = patch_repeat_pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 iteration\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.51860.52990.50000.52860.51390.03780.0378
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 iteration\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52130.54130.49730.53180.51400.04350.0436
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.53370.54940.52430.54340.53370.06770.0677
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52270.54080.49730.53330.51470.04630.0464
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52270.54080.49730.53330.51470.04630.0464
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52130.54130.49730.53180.51400.04350.0436
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 iteration\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.53780.55660.53510.54700.54100.07570.0757
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.53780.55660.53510.54700.54100.07570.0757
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.54200.54760.54050.55100.54570.08390.0839
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.54200.54760.54050.55100.54570.08390.0839
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.54470.54810.54590.55340.54970.08930.0893
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4 iteration\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.55430.57320.57030.56120.56570.10810.1081
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.54880.57090.55950.55650.55800.09730.0973
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.54880.57090.55950.55650.55800.09730.0973
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.54880.57090.55950.55650.55800.09730.0973
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.55020.56990.56760.55700.56220.09980.0998
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "metric_param = {\n", + " \"Accuracy\": 0.1,\n", + " \"AUC\": 0.1,\n", + " \"Recall\": 0.1,\n", + " \"Precision\": 0.1,\n", + " \"F1\": 0.1,\n", + " \"Kappa\": -1.0,\n", + " \"MCC\": -1.0,\n", + " }\n", + "feat_sel = FeatureSelection(target=target,\n", + " dataset=train_data.dropna(),#[list(set(new_subset+new_feat+[target]))],\n", + " target_features=500,\n", + " filter_metrics=metric_param,\n", + " include=[\"lr\"],\n", + " setup_kwargs=setup_kwargs,\n", + " optimize=True,\n", + " opt_list=[\"AUC\" , \"Accuracy\" , \"Precision\" , \"Recall\"],\n", + " number_features = 0.56\n", + " )\n", + "triplet_selected_features = feat_sel.repeat_pipeline()\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "456" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(triplet_selected_features\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(145,\n", + " 276,\n", + " ['ATT_h_mul_shots_mul_goals_mean_diff',\n", + " 'ATT_h_mul_shots_mul_goals_mean_diff',\n", + " 'DEF_h_mul_shots_mul_goals_mean_diff',\n", + " 'DEF_h_mul_shots_mul_goals_mean_diff',\n", + " 'accurate_cross_nocorner_std_a',\n", + " 'accurate_cross_nocorner_std_diff',\n", + " 'accurate_cross_nocorner_std_h',\n", + " 'accurate_cross_std_a',\n", + " 'accurate_cross_std_diff',\n", + " 'accurate_cross_std_h',\n", + " 'accurate_goal_kicks_std_a',\n", + " 'accurate_goal_kicks_std_diff',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_mean_diff',\n", + " 'accurate_keeper_sweeper_mean_h',\n", + " 'accurate_keeper_sweeper_std_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_launches_mean_a',\n", + " 'accurate_launches_mean_diff',\n", + " 'accurate_launches_mean_h',\n", + " 'accurate_layoffs_mean_a',\n", + " 'accurate_layoffs_mean_diff',\n", + " 'accurate_layoffs_mean_h',\n", + " 'accurate_layoffs_std_a',\n", + " 'accurate_layoffs_std_diff',\n", + " 'accurate_layoffs_std_h',\n", + " 'accurate_through_ball_mean_a',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'accurate_through_ball_mean_h',\n", + " 'accurate_throws_std_a',\n", + " 'accurate_throws_std_diff',\n", + " 'accurate_throws_std_h',\n", + " 'att_freekick_miss_mean_a',\n", + " 'att_freekick_miss_mean_diff',\n", + " 'att_freekick_miss_mean_h',\n", + " 'att_freekick_miss_std_a',\n", + " 'att_freekick_miss_std_diff',\n", + " 'att_freekick_miss_std_h',\n", + " 'att_goal_low_centre_mean_a',\n", + " 'att_goal_low_centre_mean_diff',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_diff',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_goal_low_right_mean_a',\n", + " 'att_goal_low_right_mean_diff',\n", + " 'att_goal_low_right_mean_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_diff',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_target_mean_diff',\n", + " 'att_hd_target_mean_h',\n", + " 'att_lf_goal_mean_a',\n", + " 'att_lf_goal_mean_diff',\n", + " 'att_lf_goal_mean_h',\n", + " 'att_lf_goal_std_a',\n", + " 'att_lf_goal_std_diff',\n", + " 'att_lf_goal_std_h',\n", + " 'att_miss_high_left_std_a',\n", + " 'att_miss_high_left_std_diff',\n", + " 'att_miss_high_left_std_h',\n", + " 'att_obox_blocked_mean_a',\n", + " 'att_obox_blocked_mean_diff',\n", + " 'att_obox_blocked_mean_h',\n", + " 'att_pen_goal_mean_a',\n", + " 'att_pen_goal_mean_diff',\n", + " 'att_pen_goal_mean_h',\n", + " 'attempts_conceded_ibox_std_a',\n", + " 'attempts_conceded_ibox_std_diff',\n", + " 'attempts_conceded_ibox_std_h',\n", + " 'attempts_conceded_obox_std_a',\n", + " 'attempts_conceded_obox_std_diff',\n", + " 'attempts_conceded_obox_std_h',\n", + " 'attempts_obox_mean_a',\n", + " 'attempts_obox_mean_diff',\n", + " 'attempts_obox_mean_h',\n", + " 'big_chance_created_mean_a',\n", + " 'big_chance_created_mean_diff',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_a',\n", + " 'big_chance_created_std_diff',\n", + " 'big_chance_created_std_h',\n", + " 'big_chance_missed_std_a',\n", + " 'big_chance_missed_std_diff',\n", + " 'big_chance_missed_std_h',\n", + " 'blocked_cross_mean_a',\n", + " 'blocked_cross_mean_diff',\n", + " 'blocked_cross_mean_h',\n", + " 'contentious_decision_mean_a',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_mean_h',\n", + " 'contentious_decision_std_a',\n", + " 'contentious_decision_std_diff',\n", + " 'contentious_decision_std_h',\n", + " 'defender_goals_mean_a',\n", + " 'defender_goals_mean_a',\n", + " 'defender_goals_mean_diff',\n", + " 'defender_goals_mean_diff',\n", + " 'defender_goals_mean_h',\n", + " 'defender_goals_mean_h',\n", + " 'diving_save_std_a',\n", + " 'diving_save_std_diff',\n", + " 'diving_save_std_h',\n", + " 'effective_head_clearance_mean_a',\n", + " 'effective_head_clearance_mean_diff',\n", + " 'effective_head_clearance_mean_h',\n", + " 'forward_goals_mean_a',\n", + " 'forward_goals_mean_diff',\n", + " 'forward_goals_mean_h',\n", + " 'goal_assist_deadball_std_a',\n", + " 'goal_assist_deadball_std_diff',\n", + " 'goal_assist_deadball_std_h',\n", + " 'goal_assist_intent_norm_mean_a',\n", + " 'goal_assist_intent_norm_mean_diff',\n", + " 'goal_assist_intent_norm_mean_h',\n", + " 'goal_assist_intentional_mean_a',\n", + " 'goal_assist_intentional_mean_diff',\n", + " 'goal_assist_intentional_mean_h',\n", + " 'goal_assist_intentional_std_a',\n", + " 'goal_assist_intentional_std_diff',\n", + " 'goal_assist_intentional_std_h',\n", + " 'goal_assist_mean_a',\n", + " 'goal_assist_mean_diff',\n", + " 'goal_assist_mean_h',\n", + " 'goal_assist_openplay_std_a',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_mean_a',\n", + " 'goal_assist_setplay_mean_diff',\n", + " 'goal_assist_setplay_mean_h',\n", + " 'goals_2t_mean_a',\n", + " 'goals_2t_mean_diff',\n", + " 'goals_2t_mean_h',\n", + " 'goals_mean_a',\n", + " 'goals_mean_diff',\n", + " 'goals_mean_h',\n", + " 'goals_openplay_mean_a',\n", + " 'goals_openplay_mean_diff',\n", + " 'goals_openplay_mean_h',\n", + " 'high_to_low_goals_mean_a',\n", + " 'high_to_low_goals_mean_diff',\n", + " 'high_to_low_goals_mean_h',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'left_div_right_foot_goals_mean_a',\n", + " 'left_div_right_foot_goals_mean_a',\n", + " 'left_div_right_foot_goals_mean_diff',\n", + " 'left_div_right_foot_goals_mean_diff',\n", + " 'left_div_right_foot_goals_mean_h',\n", + " 'left_div_right_foot_goals_mean_h',\n", + " 'lost_corners_mean_a',\n", + " 'lost_corners_mean_diff',\n", + " 'lost_corners_mean_h',\n", + " 'midfielder_goals_mean_a',\n", + " 'midfielder_goals_mean_diff',\n", + " 'midfielder_goals_mean_h',\n", + " 'no_foot_goals_ratio_mean_a',\n", + " 'no_foot_goals_ratio_mean_diff',\n", + " 'no_foot_goals_ratio_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_diff',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_over_corners_11.5',\n", + " 'odd_ratio_under_corners_10.5',\n", + " 'odds_away_over_cards_5.5_a',\n", + " 'odds_away_over_cards_5.5_diff',\n", + " 'odds_away_over_cards_5.5_h',\n", + " 'odds_home_under_cards_5.5_a',\n", + " 'odds_home_under_cards_5.5_diff',\n", + " 'odds_home_under_cards_5.5_h',\n", + " 'odds_home_under_goals_0.5_a',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'odds_home_under_goals_0.5_h',\n", + " 'ontarget_att_assist_mean_a',\n", + " 'ontarget_att_assist_mean_diff',\n", + " 'ontarget_att_assist_mean_h',\n", + " 'own_goals_mean_a',\n", + " 'own_goals_mean_diff',\n", + " 'own_goals_mean_h',\n", + " 'penalty_conceded_mean_a',\n", + " 'penalty_conceded_mean_diff',\n", + " 'penalty_conceded_mean_h',\n", + " 'penalty_faced_std_a',\n", + " 'penalty_faced_std_diff',\n", + " 'penalty_faced_std_h',\n", + " 'penalty_save_std_a',\n", + " 'penalty_save_std_diff',\n", + " 'penalty_save_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'ratio_over_corners_11.5_a',\n", + " 'ratio_over_corners_11.5_diff',\n", + " 'ratio_over_corners_11.5_h',\n", + " 'ratio_under_corners_10.5_a',\n", + " 'ratio_under_corners_10.5_diff',\n", + " 'ratio_under_corners_10.5_h',\n", + " 'red_card_std_a',\n", + " 'red_card_std_diff',\n", + " 'red_card_std_h',\n", + " 'rescinded_red_card_std_a',\n", + " 'rescinded_red_card_std_diff',\n", + " 'rescinded_red_card_std_h',\n", + " 'right_to_left_goals_mean_a',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_mean_h',\n", + " 'saves_std_a',\n", + " 'saves_std_diff',\n", + " 'saves_std_h',\n", + " 'shots_mul_goals_mean_a',\n", + " 'shots_mul_goals_mean_a',\n", + " 'shots_mul_goals_mean_diff',\n", + " 'shots_mul_goals_mean_diff',\n", + " 'shots_mul_goals_mean_h',\n", + " 'shots_mul_goals_mean_h',\n", + " 'shots_std_a',\n", + " 'shots_std_diff',\n", + " 'shots_std_h',\n", + " 'total_fastbreak_std_a',\n", + " 'total_fastbreak_std_diff',\n", + " 'total_fastbreak_std_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_diff',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_keeper_sweeper_std_a',\n", + " 'total_keeper_sweeper_std_diff',\n", + " 'total_keeper_sweeper_std_h',\n", + " 'total_launches_mean_a',\n", + " 'total_launches_mean_diff',\n", + " 'total_launches_mean_h',\n", + " 'total_launches_std_a',\n", + " 'total_launches_std_diff',\n", + " 'total_launches_std_h',\n", + " 'total_layoffs_std_a',\n", + " 'total_layoffs_std_diff',\n", + " 'total_layoffs_std_h',\n", + " 'total_red_card_std_a',\n", + " 'total_red_card_std_diff',\n", + " 'total_red_card_std_h',\n", + " 'total_through_ball_mean_a',\n", + " 'total_through_ball_mean_diff',\n", + " 'total_through_ball_mean_h',\n", + " 'total_through_ball_std_a',\n", + " 'total_through_ball_std_diff',\n", + " 'total_through_ball_std_h',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_throws_std_h',\n", + " 'total_win_pct_over_goals_2.5_a',\n", + " 'total_win_pct_over_goals_2.5_diff',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_1.5_diff',\n", + " 'total_win_pct_under_goals_1.5_h',\n", + " 'total_win_pct_under_goals_3.5_a',\n", + " 'total_win_pct_under_goals_3.5_diff',\n", + " 'total_win_pct_under_goals_3.5_h',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_over_goals_2.5_h',\n", + " 'win_pct_home_over_cards_6.5_a',\n", + " 'win_pct_home_over_cards_6.5_diff',\n", + " 'win_pct_home_over_cards_6.5_h',\n", + " 'win_pct_home_over_goals_2.5_a',\n", + " 'win_pct_home_over_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_cards_4.5_a',\n", + " 'win_pct_home_under_cards_4.5_diff',\n", + " 'win_pct_home_under_cards_4.5_h',\n", + " 'won_corners_ratio_std_a',\n", + " 'won_corners_ratio_std_diff',\n", + " 'won_corners_ratio_std_h'])" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "common_feat = list(set([\"_\".join(x.split(\"_\")[:-1]) for x in selected_features]))\n", + "new_subset = [x for x in train_data.columns for c in common_feat if c in x]\n", + "\n", + "len(selected_features), len(new_subset), sorted(new_subset)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### new imports " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import os\n", + "\n", + "from ml_bets.constants import FEATURES_PATH\n", + "from ml_bets.features.features import Features\n", + "from ml_bets.modeling.match_model import PipelineDatasets, run_pycaret_setup\n", + "#from featsel.feature_selection import FeatureSelection\n", + "\n", + "from pycaret.utils import check_metric\n", + "from pycaret.classification import (add_metric, calibrate_model, optimize_threshold,\n", + " create_model,\n", + " finalize_model,\n", + " optimize_threshold, \n", + " save_model,\n", + " compare_models, \n", + " evaluate_model,\n", + " get_config,\n", + " setup,\n", + " tune_model,\n", + " predict_model,\n", + ")\n", + "\n", + "from ml_bets.supplementary.functions import IGNORE_FEATURES\n", + "from ml_bets.research.datasets import create_dataset\n", + "from ml_bets.features.names.goals import GOALS_FEATURES, NEW_FEATURES" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "from ml_bets.research.tips import calibrate_tips, tips_from_model, combine_tips, predict_dataset, compose_tips, get_tip_probs" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "ix = np.logical_and(feats.matches[\"date\"].dt.month > 10,\n", + " feats.matches[\"competition\"].isin({\"mexican_primera\", 'us_major_league_soccer'}))\n", + "index = feats.matches[~ix].index" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "test_feats = ['acc_cross_nocorner_pct_std_a',\n", + " 'acc_cross_nocorner_pct_std_diff',\n", + " 'acc_cross_nocorner_pct_std_h',\n", + " 'accurate_flick_on_mean_h',\n", + " 'accurate_flick_on_mean_a',\n", + " 'accurate_freekick_cross_mean_a',\n", + " 'accurate_freekick_cross_mean_diff',\n", + " 'accurate_freekick_cross_mean_h',\n", + " 'accurate_goal_kicks_mean_diff',\n", + " 'accurate_goal_kicks_std_a',\n", + " 'accurate_goal_kicks_std_diff',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_pass_std_a',\n", + " 'accurate_pass_std_h',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'att_assist_openplay_std_a',\n", + " 'att_assist_openplay_std_h',\n", + " 'att_cmiss_left_mean_a',\n", + " 'att_cmiss_left_mean_h',\n", + " 'att_cmiss_left_std_a',\n", + " 'att_cmiss_left_std_diff',\n", + " 'att_cmiss_left_std_h',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_low_centre_mean_diff',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_target_mean_h',\n", + " 'att_ibox_own_goal_mean_diff',\n", + " 'att_ibox_own_goal_std_h',\n", + " 'att_ibox_own_goal_std_a',\n", + " 'att_miss_high_mean_a',\n", + " 'att_miss_high_mean_h',\n", + " 'att_miss_high_right_mean_diff',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_one_on_one_mean_h',\n", + " 'att_one_on_one_mean_a',\n", + " 'att_one_on_one_std_diff',\n", + " 'att_one_on_one_std_h',\n", + " 'att_post_high_std_a',\n", + " 'att_post_high_std_h',\n", + " 'att_post_right_mean_a',\n", + " 'att_post_right_mean_h',\n", + " 'attempts_ibox_std_a',\n", + " 'attempts_ibox_std_h',\n", + " 'backward_pass_mean_diff',\n", + " 'backward_pass_mean_h',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_diff',\n", + " 'clean_sheet_std_diff',\n", + " 'contentious_decision_mean_a',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_std_a',\n", + " 'contentious_decision_std_h',\n", + " 'duel_won_pct_mean_diff',\n", + " 'effective_clearance_mean_diff',\n", + " 'error_lead_to_goal_mean_diff',\n", + " 'error_lead_to_goal_std_diff',\n", + " 'first_yellow_card_1t_mean_h',\n", + " 'first_yellow_card_1t_mean_a',\n", + " 'foul_throw_in_std_diff',\n", + " 'fouled_final_third_mean_diff',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_std_a',\n", + " 'goal_assist_setplay_std_diff',\n", + " 'goal_assist_setplay_std_h',\n", + " 'goal_assist_std_diff',\n", + " 'goals_mean_diff',\n", + " 'goals_openplay_std_h',\n", + " 'goals_openplay_std_a',\n", + " 'good_high_claim_mean_diff',\n", + " 'high_to_low_goals_mean_a',\n", + " 'high_to_low_goals_mean_diff',\n", + " 'high_to_low_goals_std_a',\n", + " 'high_to_low_goals_std_h',\n", + " 'imp_prob_under_goals_0.5_h',\n", + " 'imp_prob_under_goals_2.5_diff',\n", + " 'interception_mean_a',\n", + " 'interception_mean_diff',\n", + " 'interception_mean_h',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_a',\n", + " 'last_man_tackle_mean_diff',\n", + " 'left_div_right_foot_goals_std_diff',\n", + " 'leftside_pass_mean_a',\n", + " 'leftside_pass_mean_h',\n", + " 'leftside_pass_std_a',\n", + " 'long_pass_own_to_opp_mean_diff',\n", + " 'long_pass_own_to_opp_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_diff',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_under_corners_10.5',\n", + " 'odd_ratio_under_corners_8.5',\n", + " 'odds_home_under_both_score_h',\n", + " 'odds_away_under_both_score_a',\n", + " 'odds_away_under_goals_4.5_a',\n", + " 'odds_home_under_goals_4.5_h',\n", + " 'odds_away_over_goals_4.5_a',\n", + " 'odds_home_over_goals_4.5_h',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'odds_home_under_goals_0.5_h',\n", + " 'own_goals_std_h',\n", + " 'own_goals_std_a',\n", + " 'pen_goals_conceded_mean_diff',\n", + " 'penalty_faced_std_a',\n", + " 'penalty_won_std_a',\n", + " 'penalty_faced_std_h',\n", + " 'penalty_won_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'post_scoring_att_std_a',\n", + " 'post_scoring_att_std_h',\n", + " 'prob_squared_under_goals_2.5',\n", + " 'pts_dropped_winning_pos_mean_a',\n", + " 'pts_dropped_winning_pos_std_diff',\n", + " 'pts_dropped_winning_pos_std_h',\n", + " 'ratio_over_goals_2.5_a',\n", + " 'ratio_over_goals_2.5_h',\n", + " 'ratio_under_goals_2.5_a',\n", + " 'ratio_under_goals_2.5_diff',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_over_goals_3.5',\n", + " 'raw_prob_under_goals_1.5',\n", + " 'raw_prob_under_goals_2.5',\n", + " 'raw_prob_under_goals_3.5',\n", + " 'raw_prob_under_goals_4.5',\n", + " 'red_card_1t_mean_a',\n", + " 'red_card_1t_mean_diff',\n", + " 'red_card_1t_mean_h',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_2t_mean_diff',\n", + " 'red_card_mean_h',\n", + " 'red_card_mean_a',\n", + " 'red_card_std_diff',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_std_diff',\n", + " 'rightside_pass_div_leftside_pass_mean_a',\n", + " 'rightside_pass_div_leftside_pass_mean_h',\n", + " 'second_yellow_mean_h',\n", + " 'shots_mul_goals_std_h',\n", + " 'second_yellow_mean_a',\n", + " 'shots_mul_goals_std_a',\n", + " 'successful_final_third_passes_mean_a',\n", + " 'successful_final_third_passes_mean_diff',\n", + " 'successful_final_third_passes_std_a',\n", + " 'successful_final_third_passes_std_diff',\n", + " 'successful_put_through_std_a',\n", + " 'successful_put_through_std_diff',\n", + " 'successful_put_through_std_h',\n", + " 'total_clearance_mean_a',\n", + " 'total_clearance_mean_h',\n", + " 'total_fastbreak_std_diff',\n", + " 'total_high_claim_mean_a',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_high_claim_mean_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_launches_std_h',\n", + " 'total_launches_std_a',\n", + " 'total_red_card_mean_h',\n", + " 'total_red_card_mean_a',\n", + " 'total_red_card_std_diff',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_win_pct_over_goals_1.5_a',\n", + " 'total_win_pct_over_goals_1.5_h',\n", + " 'total_win_pct_over_goals_2.5_a',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_over_goals_3.5_a',\n", + " 'total_win_pct_over_goals_3.5_h',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_1.5_h',\n", + " 'total_win_pct_under_goals_2.5_a',\n", + " 'total_win_pct_under_goals_2.5_h',\n", + " 'total_win_pct_under_goals_3.5_a',\n", + " 'total_yel_card_std_a',\n", + " 'total_yel_card_std_diff',\n", + " 'total_yel_card_std_h',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_under_goals_2.5_a',\n", + " 'win_pct_away_under_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_a',\n", + " 'win_pct_home_over_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_goals_2.5_diff',\n", + " 'win_pct_home_under_goals_2.5_h',\n", + " 'winner_mean_diff']" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def setup_dataset(test_date):\n", + " ds = create_dataset(target=target,\n", + " test_date=test_date,\n", + " features=feats,\n", + " odds_features=True,\n", + " include_std=True,\n", + " test_weeks=6,\n", + " ignore_features=IGNORE_FEATURES,\n", + " drop_future_matches=False,\n", + " )\n", + " train_data = ds.train_data.copy()#[ds.train_data.index.map(lambda x: \"us_major_league_soccer\" not in x and \"mexican\" not in x)]\n", + " train_data.drop(columns=[\"hour_rank\", \"hour_before_16\", \"is_weekend\"], inplace=True)\n", + " train_data = train_data[train_data.index.isin(index)][list(set(test_feats)) + [target]].copy()#.reset_index(drop=True)\n", + " test_data = ds.test_set[ds.test_set.index.isin(index)][list(set(test_feats)) + [target]].copy()#.reset_index(drop=True)\n", + " val_data = ds.val_set[ds.val_set.index.isin(index)].copy()\n", + " setup_kwargs = dict(\n", + " preprocess=True,\n", + " test_data=test_data[train_data.columns.tolist()],#.dropna(),\n", + " #numeric_features=[x for x in train_data.columns.tolist() if x != target],\n", + " #custom_pipeline=loaded,\n", + " #train_size=0.75,\n", + " session_id=123,\n", + " normalize=True,\n", + " normalize_method=\"robust\",\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.8,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " #ignore_features=ignore_features,\n", + " fold_strategy=\"stratifiedkfold\",#\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=4,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.5,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"linear\",\n", + " pca_components=30,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.05,\n", + " trigonometry_features=False,\n", + " remove_outliers=True,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.05,\n", + " fix_imbalance=True,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " )\n", + " _ = setup(data=train_data, target=target, **setup_kwargs)\n", + " return train_data, test_data, val_data, ds" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "train_data, test_data, val_data, ds = setup_dataset(\"4-Dec-2021\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "from pycaret.classification import stack_models, ensemble_model, blend_models\n", + "def train_ensemble():\n", + " top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"et\", \"rf\", \"svm\"],\n", + " verbose=True,\n", + " )\n", + " tuned_models = [tune_model(model, optimize=\"MCC\", choose_better=True, n_iter=50, search_library=\"optuna\") for model in top_models]\n", + " cali = [calibrate_model(tuned, method=\"sigmoid\", calibrate_fold=4) for tuned in tuned_models]\n", + " blend = blend_models(cali)\n", + " opti = tune_model(blend, optimize=\"Precision\", choose_better=True, n_iter=50, search_library=\"optuna\")\n", + " return opti, cali, tuned_models" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "from pycaret.classification import stack_models, ensemble_model, blend_models\n", + "def train_linear_models():\n", + " top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"svm\"],\n", + " verbose=True,\n", + " )\n", + " tuned_models = [tune_model(model, optimize=\"MCC\", choose_better=True, n_iter=50, search_library=\"optuna\") for model in top_models]\n", + " cali = [calibrate_model(tuned, method=\"sigmoid\", calibrate_fold=4) for tuned in tuned_models]\n", + " return tuned_models, cali" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Accuracy AUC Recall Prec. F1 Kappa MCC
00.64140.68930.67160.65070.66100.28060.2807
10.59970.65860.63210.61240.62210.19690.1970
20.62160.66790.61230.64420.62780.24350.2439
30.61260.64750.60150.63450.61750.22570.2260
Mean0.61880.66580.62940.63540.63210.23670.2369
SD0.01520.01540.02670.01450.01710.03030.0303
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tuned_linear, cali_linear = train_linear_models()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC TT (Sec)
lrLogistic Regression0.61660.67340.58360.65000.60810.23510.24000.3000
ldaLinear Discriminant Analysis0.61660.67050.58920.64750.61150.23470.23870.3025
ridgeRidge Classifier0.61660.00000.58920.64760.61150.23470.23870.2850
svmSVM - Linear Kernel0.58410.00000.54410.61570.57340.17080.17390.3050
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"svm\"],\n", + " verbose=True,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "SGDClassifier(alpha=0.10126692364605047, average=False, class_weight=None,\n", + " early_stopping=False, epsilon=0.1, eta0=0.001022673152073415,\n", + " fit_intercept=False, l1_ratio=0.2203376725525369,\n", + " learning_rate='optimal', loss='hinge', max_iter=1000,\n", + " n_iter_no_change=5, n_jobs=-1, penalty='l1', power_t=0.5,\n", + " random_state=123, shuffle=True, tol=0.001,\n", + " validation_fraction=0.1, verbose=0, warm_start=False)" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tuned_linear[3]" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6522b430b2a64128ac3789a8d93475f2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(tuned_linear[3])" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a9de03ccce3a4047b615b146297be69e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(cali_linear[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "market=\"goals\"\n", + "cutoff = 2.5\n", + "tips = tips_from_model(model=cali_linear[0],\n", + " test_data=test_data,\n", + " features=feats,\n", + " market=market,\n", + " cutoff=cutoff,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
winprofitexp_payoffexp_payoff_precoddsconfidencecountbuenasmodel
bet_typematch_week
goals_over_2.52021_190.8181820.4345451.193888NaN1.7436360.683591119model
2021_200.7000000.1440001.087417NaN1.6410000.664270107model
2021_210.8000000.3590001.130386NaN1.6850000.671600108model
2021_220.5714290.0400001.130597NaN1.7085710.66280074model
2021_230.500000-0.1400001.216788NaN1.8150000.66775042model
2021_240.6250000.0587501.168317NaN1.7300000.67497585model
2021_250.000000-1.0000001.200240NaN1.8000000.66680010model
goals_under_2.52021_190.7500000.2550001.034973NaN1.6300000.63415043model
2021_200.8000000.3720001.142580NaN1.7060000.67048054model
2021_210.333333-0.3633331.200528NaN1.7466670.68603331model
2021_221.0000000.6700001.025046NaN1.6700000.61380011model
2021_230.000000-1.0000001.011686NaN1.6700000.60580010model
2021_241.0000000.7550001.155859NaN1.7550000.66237544model
\n", + "
" + ], + "text/plain": [ + " win profit exp_payoff exp_payoff_prec \\\n", + "bet_type match_week \n", + "goals_over_2.5 2021_19 0.818182 0.434545 1.193888 NaN \n", + " 2021_20 0.700000 0.144000 1.087417 NaN \n", + " 2021_21 0.800000 0.359000 1.130386 NaN \n", + " 2021_22 0.571429 0.040000 1.130597 NaN \n", + " 2021_23 0.500000 -0.140000 1.216788 NaN \n", + " 2021_24 0.625000 0.058750 1.168317 NaN \n", + " 2021_25 0.000000 -1.000000 1.200240 NaN \n", + "goals_under_2.5 2021_19 0.750000 0.255000 1.034973 NaN \n", + " 2021_20 0.800000 0.372000 1.142580 NaN \n", + " 2021_21 0.333333 -0.363333 1.200528 NaN \n", + " 2021_22 1.000000 0.670000 1.025046 NaN \n", + " 2021_23 0.000000 -1.000000 1.011686 NaN \n", + " 2021_24 1.000000 0.755000 1.155859 NaN \n", + "\n", + " odds confidence count buenas model \n", + "bet_type match_week \n", + "goals_over_2.5 2021_19 1.743636 0.683591 11 9 model \n", + " 2021_20 1.641000 0.664270 10 7 model \n", + " 2021_21 1.685000 0.671600 10 8 model \n", + " 2021_22 1.708571 0.662800 7 4 model \n", + " 2021_23 1.815000 0.667750 4 2 model \n", + " 2021_24 1.730000 0.674975 8 5 model \n", + " 2021_25 1.800000 0.666800 1 0 model \n", + "goals_under_2.5 2021_19 1.630000 0.634150 4 3 model \n", + " 2021_20 1.706000 0.670480 5 4 model \n", + " 2021_21 1.746667 0.686033 3 1 model \n", + " 2021_22 1.670000 0.613800 1 1 model \n", + " 2021_23 1.670000 0.605800 1 0 model \n", + " 2021_24 1.755000 0.662375 4 4 model " + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def show_results(df, groupby=[\"bet_type\", \"match_week\"]):\n", + " ix = np.logical_and(df[\"win\"]>=0, True)# df[\"label\"]>=1)\n", + " #ix = np.logical_and(df[\"consensus\"] >=0.1, ix)\n", + " ix2 = np.logical_and(df[\"odds\"]>=1.5, df[\"odds\"]<2.)\n", + " ix = np.logical_and(ix, ix2)\n", + " #ix = np.logical_and(ix, ~df[\"validation\"])\n", + " #ix = np.logical_and(ix, df[\"exp_payoff_prec\"] >0.88)\n", + " #ix = np.logical_and(ix, df[\"exp_payoff\"] <1.2)\n", + " #ix = np.logical_and(ix, df[\"exp_payoff\"] >0.8)\n", + " ix = np.logical_and(ix, df[\"confidence\"] >=0.60)\n", + " #ix = np.logical_and(ix, df[\"confidence\"] <=0.75)\n", + " x = df[ix].groupby(groupby)[[\"win\", \"profit\", \"exp_payoff\", \"exp_payoff_prec\", \"odds\", \"confidence\"]].mean()\n", + " x[\"count\"] = df[ix].groupby(groupby)[[\"win\"]].count()\n", + " x[\"buenas\"] = df[ix].groupby(groupby)[[\"win\"]].sum().astype(int)\n", + " x[\"model\"] = df[\"model\"].iloc[0]\n", + " return x\n", + "show_results(tips)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/feat_sel_test_j2.ipynb b/notebooks/feat_sel_test_j2.ipynb new file mode 100644 index 0000000..e8808f1 --- /dev/null +++ b/notebooks/feat_sel_test_j2.ipynb @@ -0,0 +1,4977 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import product\n", + "from typing import Dict, List, Optional, Union\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import param\n", + "from pycaret.classification import (\n", + " compare_models,\n", + " create_model,\n", + " get_config,\n", + " predict_model,\n", + " setup,\n", + " tune_model,\n", + ")\n", + "from pycaret.utils import check_metric\n", + "\n", + "\n", + "\n", + "\n", + "class FeatureSelection(param.Parameterized):\n", + "\n", + " # Class attributes\n", + " model_class_to_name = {\n", + " \"RidgeClassifier\": \"ridge\",\n", + " \"LogisticRegression\": \"lr\",\n", + " \"LinearDiscriminantAnalysis\": \"lda\",\n", + " \"GradientBoostingClassifier\": \"gbc\",\n", + " \"QuadraticDiscriminantAnalysis\": \"qda\",\n", + " \"LGBMClassifier\": \"lightgbm\",\n", + " \"AdaBoostClassifier\": \"ada\",\n", + " \"RandomForestClassifier\": \"rf\",\n", + " \"ExtraTreesClassifier\": \"et\",\n", + " \"GaussianNB\": \"nb\",\n", + " \"DecisionTreeClassifier\": \"dt\",\n", + " \"KNeighborsClassifier\": \"knn\",\n", + " \"SGDClassifier\": \"svm\",\n", + " \"CatBoostClassifier\": \"catboost\",\n", + " \"SVC\": \"rbfsvm\",\n", + " \"GaussianProcessClassifier\": \"gpc\",\n", + " \"MLPClassifier\": \"mlp\",\n", + " \"XGBClassifier\": \"xgboost\",\n", + " }\n", + "\n", + " metrics_list = [\"Accuracy\", \"AUC\", \"Recall\", \"Precision\", \"F1\", \"Kappa\", \"MCC\"]\n", + "\n", + " # Private class attributes\n", + " _filter_metric = {\n", + " \"Accuracy\": 0.5,\n", + " \"AUC\": 0.5,\n", + " \"Recall\": 0.6,\n", + " \"Precision\": 0.6,\n", + " \"F1\": 0.6,\n", + " \"Kappa\": 0.1,\n", + " \"MCC\": 0.1,\n", + " }\n", + "\n", + " _setup_kwargs = dict(\n", + " preprocess=True,\n", + " train_size=0.75,\n", + " # test_data=test_data,\n", + " session_id=123,\n", + " normalize=True,\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.4,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " ignore_features=None,\n", + " fold_strategy=\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=4,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.4,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"kernel\",\n", + " pca_components=30,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.01,\n", + " trigonometry_features=False,\n", + " remove_outliers=False,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.01,\n", + " fix_imbalance=False,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " html=False,\n", + " )\n", + "\n", + " _numerics = [\"int16\", \"int32\", \"int64\", \"float16\", \"float32\", \"float64\", \"int\", \"float\"]\n", + "\n", + " # Init values\n", + " ## Feature selection parameters\n", + " target = param.String(\"goal_2.5\")\n", + " number_features = param.Number(\n", + " 0.5,\n", + " bounds=(0, 1),\n", + " inclusive_bounds=(False, False),\n", + " doc=\"Number of features (percentage) selected each iteration. Only the first nth \"\n", + " \"features will be kept for the next iteration.\",\n", + " )\n", + " target_features = param.Number(\n", + " 0.3,\n", + " bounds=(0, None),\n", + " inclusive_bounds=(False, True),\n", + " doc=\"Final total number of features. The goal of the package is to reduce \"\n", + " \"the incoming columns of the dataset to this 'target_features' number.\",\n", + " )\n", + " ## Metric parameters\n", + " filter_metrics = param.Dict(_filter_metric)\n", + " ## Model setup and model optimization parameters\n", + " numerics = param.List(_numerics)\n", + " ignore_features = param.List(default=[], allow_None=True)\n", + " setup_kwargs = param.Dict(_setup_kwargs)\n", + " include = param.List(default=None, item_type=str, allow_None=True)\n", + " exclude = param.List([\"qda\", \"knn\", \"nb\"], item_type=str)\n", + " sort = param.String(\"AUC\")\n", + " number_models = param.Integer(10, bounds=(2, 13))\n", + " top_models = param.List(default=None, allow_None=True)\n", + " optimize = param.Boolean(False)\n", + " opt_list = param.List([\"Accuracy\", \"Precision\", \"Recall\", \"F1\", \"AUC\"], item_type=str)\n", + " ## Class selectors\n", + " dataset = param.ClassSelector(class_=pd.DataFrame)\n", + " dict_models = param.ClassSelector(class_=dict)\n", + " tune_dict_models = param.ClassSelector(class_=dict)\n", + " x_train = param.ClassSelector(class_=pd.DataFrame)\n", + " x_df = param.DataFrame(pd.DataFrame())\n", + " model_df = param.ClassSelector(class_=pd.DataFrame)\n", + " model_tuned_df = param.ClassSelector(class_=pd.DataFrame)\n", + " features_df = param.ClassSelector(class_=pd.DataFrame)\n", + "\n", + " def __init__(self, dataset: pd.DataFrame, **kwargs):\n", + " # Copy of the incoming dataset\n", + " dataset = dataset.copy()\n", + " # Compute the upper bound of number_features, target_features, number_models\n", + " total_features = dataset.shape[1]\n", + " self.param.target_features.bounds = (0, total_features)\n", + " if \"include\" in kwargs:\n", + " self.param.number_models.default = len(kwargs[\"include\"])\n", + " self.param.number_models.bounds = (0, len(kwargs[\"include\"]))\n", + " # Call super\n", + " super(FeatureSelection, self).__init__(dataset=dataset, **kwargs)\n", + " # Get the features of the dataframe\n", + " self.feature_list = self.dataset.columns.tolist()\n", + " self.feature_list.remove(self.target) # target column should not be counted\n", + " # Compute target features\n", + " self.target_features = self.calculate_number_features(\n", + " number_features=self.target_features, features=self.feature_list\n", + " )\n", + " # Get the evaluator and the arguments. Depends on the \"include\" parameter\n", + " self._training_function, self._args = self._decide_model_eval()\n", + " # Get all the columns whose type is numeric\n", + " self.numeric_features = self._compute_numeric_features(df=self.dataset[self.feature_list])\n", + "\n", + " def _compute_numeric_features(self, df: pd.DataFrame):\n", + " \"\"\"Return those columns from the given dataset whose data type is numeric.\"\"\"\n", + " return df.select_dtypes(include=self.numerics).columns.tolist()\n", + "\n", + " def _decide_model_eval(self):\n", + " \"\"\"\n", + " Define the pycaret model evaluator depending on the number of included models.\n", + "\n", + " If the 'include' list parameter equals 1, the method will return\n", + " the 'create_models' pycaret object.\n", + " If 'include' parameter list is greatear than 1, the method will\n", + " return the 'compare_model' pycaret object and its arguments.\n", + " If 'include' parameter equals None, the method will return the\n", + " 'compare_models' pycaret object, where all possible models are\n", + " considered for evaluation, except those included within the 'exclude'\n", + " list.\n", + " \"\"\"\n", + " args = {\"n_select\": self.number_models, \"sort\": self.sort, \"verbose\": False}\n", + " training_function = compare_models\n", + " if not self.include:\n", + " args[\"exclude\"] = self.exclude\n", + " elif len(self.include) == 1:\n", + " training_function = lambda *rgs, **kwargs: [create_model(*rgs, **kwargs)]\n", + " args = {\"estimator\": self.include[0], \"verbose\": False}\n", + " else:\n", + " args[\"include\"] = self.include\n", + " return training_function, args\n", + "\n", + " @staticmethod\n", + " def calculate_number_features(\n", + " number_features: Union[int, float], features: Union[pd.DataFrame, List]\n", + " ) -> int:\n", + " n_features = (\n", + " int(number_features)\n", + " if (number_features >= 1)\n", + " else int(number_features * len(features))\n", + " )\n", + " return n_features\n", + "\n", + " def train_model(self):\n", + " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", + " # Selected dataset\n", + " selected_cols = self.feature_list + [self.target]\n", + " train_data = self.dataset[selected_cols] if self.x_df.empty else self.x_df[selected_cols]\n", + " # Numeric features\n", + " self.setup_kwargs[\"numeric_features\"] = [\n", + " c for c in self.numeric_features if c in self.feature_list\n", + " ]\n", + " # Ignore features\n", + " self.setup_kwargs[\"ignore_features\"] = [\n", + " c for c in self.ignore_features if c in self.feature_list\n", + " ]\n", + " # Initialize pycaret setup\n", + " setup(data=train_data, target=self.target, **self.setup_kwargs)\n", + " # Get train dataset and preprocessed dataframe\n", + " self.x_train = get_config(\"X_train\")\n", + " if self.x_df.empty: # TODO change x_df by dataset and add flag?\n", + " self.x_df = pd.concat([get_config(\"X\"), get_config(\"y\")], axis=1)\n", + " self.setup_kwargs[\"preprocess\"] = False # Turn off preprocessing\n", + " # Compare models\n", + " self.top_models = self._training_function(**self._args)\n", + "\n", + " def create_dict_models(self):\n", + " \"\"\"Create a dictionary whose values are pycaret standard models.\"\"\"\n", + " self.dict_models = {\n", + " str(top_model).split(\"(\")[0]: top_model for top_model in self.top_models\n", + " }\n", + " # Remove bad catboost key\n", + " oldkey = [key for key in self.dict_models.keys() if key.startswith(\" self.target_features:\n", + " # Call iteration\n", + " self.create_feature_list()\n", + " if len(self.feature_list) <= 1:\n", + " break\n", + " return self.feature_list\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import os\n", + "\n", + "from ml_bets.constants import FEATURES_PATH\n", + "from ml_bets.features.features import Features\n", + "from ml_bets.modeling.match_model import PipelineDatasets, run_pycaret_setup\n", + "\n", + "from pycaret.utils import check_metric\n", + "from pycaret.classification import (add_metric, calibrate_model, optimize_threshold,\n", + " create_model,\n", + " finalize_model,\n", + " optimize_threshold, \n", + " save_model,\n", + " compare_models, \n", + " evaluate_model,\n", + " get_config,\n", + " setup,\n", + " tune_model,\n", + " predict_model,\n", + ")\n", + "\n", + "from ml_bets.supplementary.functions import IGNORE_FEATURES\n", + "from ml_bets.research.datasets import create_dataset\n", + "from ml_bets.features.names.goals import GOALS_FEATURES, NEW_FEATURES" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "target = \"goals_2.5\"\n", + "test_date = \"1-Dec-2021\"" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ESP1C.xls\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ING1C.xls\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ITA1C.xls\n", + "Excel file c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\MEX1C.xls is empty. Skipping\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\FRA1C.xls\n", + "Excel file c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\MLS1C.xls is empty. Skipping\n", + "c:\\users\\usuario\\desktop\\data science\\ml_bets-master\\data\\future_matches\\ALE1C.xls\n" + ] + } + ], + "source": [ + "feats = Features()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def patched_create_dataset(\n", + " test_date: str,\n", + " target: str,\n", + " columns=None,\n", + " odds_features: bool = True,\n", + " summary: bool = True,\n", + " odds_rankings: bool = True,\n", + " include_std: bool = True,\n", + " features: Features = None,\n", + " ignore_features=None,\n", + " drop_future_matches: bool = True,\n", + " test_weeks: int = 4,\n", + "):\n", + " features = features or Features()\n", + " examples = features.create(\n", + " columns=columns,\n", + " odds_features=odds_features,\n", + " odds_rankings=odds_rankings,\n", + " referee_features=True,\n", + " include_std=include_std,\n", + " summary=summary,\n", + " )\n", + " examples = examples[[x for x in examples.columns if \"possession\" not in x]]\n", + " if ignore_features is not None:\n", + " examples.drop(columns=ignore_features, inplace=True)\n", + " pds = PipelineDatasets(\n", + " examples=examples,\n", + " features=features,\n", + " target=target,\n", + " drop_future_matches=drop_future_matches,\n", + " test_size=test_date,\n", + " test_weeks=test_weeks,\n", + " )\n", + " return pds" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "ds = patched_create_dataset(target=target,\n", + " test_date=test_date,\n", + " features=feats,\n", + " odds_features=True,\n", + " include_std=True,\n", + " ignore_features=IGNORE_FEATURES+[\"referee\", \"hour_rank\", \"hour_before_16\", \"is_weekend\"],\n", + " drop_future_matches=False,\n", + " \n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "train_data = ds.train_data.copy()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "setup_kwargs = dict(\n", + " preprocess=True,\n", + " #custom_pipeline=loaded,\n", + " train_size=0.75,\n", + " session_id=123,\n", + " normalize=True,\n", + " # normalize_method=\"robust\",\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.8,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " #ignore_features=ignore_features,\n", + " fold_strategy=\"stratifiedkfold\",#\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=3,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.5,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"kernel\",\n", + " pca_components=50,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.05,\n", + " trigonometry_features=False,\n", + " remove_outliers=True,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.05,\n", + " fix_imbalance=True,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feature selection (without triplet)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.51860.52990.50000.52860.51390.03780.0378
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.51310.54000.50270.52250.51240.02650.0265
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52960.54890.52970.53850.53410.05910.0591
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50340.53860.48110.51300.49650.00770.0077
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52130.54230.50810.53110.51930.04310.0431
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.52960.54890.52970.53850.53410.05910.0591
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "metric_param = {\n", + " \"Accuracy\": 0.1,\n", + " \"AUC\": 0.1,\n", + " \"Recall\": 0.1,\n", + " \"Precision\": 0.1,\n", + " \"F1\": 0.1,\n", + " \"Kappa\": -1.0,\n", + " \"MCC\": -1.0,\n", + " }\n", + "feat_sel = FeatureSelection(target=target,\n", + " dataset=train_data.dropna(),#[list(set(new_subset+new_feat+[target]))],\n", + " target_features=500,\n", + " filter_metrics=metric_param,\n", + " include=[\"lr\"],\n", + " setup_kwargs=setup_kwargs,\n", + " optimize=True,\n", + " opt_list=[\"AUC\" , \"Accuracy\" , \"Precision\" , \"Recall\"],\n", + " number_features = 0.56\n", + " )\n", + "selected_features = feat_sel.repeat_pipeline()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "355" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(selected_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['DEF_mean_a',\n", + " 'MED_mean_diff',\n", + " 'acc_corners_intobox_pct_std_a',\n", + " 'accurate_back_zone_pass_std_a',\n", + " 'accurate_chipped_pass_std_diff',\n", + " 'accurate_cross_nocorner_std_diff',\n", + " 'accurate_cross_std_a',\n", + " 'accurate_cross_std_h',\n", + " 'accurate_fwd_zone_pass_mean_diff',\n", + " 'accurate_fwd_zone_pass_std_a',\n", + " 'accurate_fwd_zone_pass_std_h',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_mean_diff',\n", + " 'accurate_keeper_sweeper_mean_h',\n", + " 'accurate_keeper_sweeper_std_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_keeper_throws_std_diff',\n", + " 'accurate_launches_mean_a',\n", + " 'accurate_launches_std_a',\n", + " 'accurate_layoffs_mean_a',\n", + " 'accurate_layoffs_std_a',\n", + " 'accurate_layoffs_std_diff',\n", + " 'accurate_pass_std_a',\n", + " 'accurate_pass_std_diff',\n", + " 'accurate_pull_back_mean_diff',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'accurate_throws_std_a',\n", + " 'accurate_throws_std_diff',\n", + " 'accurate_throws_std_h',\n", + " 'att_assist_openplay_mean_a',\n", + " 'att_bx_right_mean_h',\n", + " 'att_bx_right_std_diff',\n", + " 'att_cmiss_high_mean_h',\n", + " 'att_cmiss_left_std_a',\n", + " 'att_cmiss_left_std_h',\n", + " 'att_corner_mean_a',\n", + " 'att_corner_ratio_mean_a',\n", + " 'att_fastbreak_std_h',\n", + " 'att_freekick_goal_std_diff',\n", + " 'att_freekick_miss_mean_h',\n", + " 'att_freekick_miss_std_a',\n", + " 'att_freekick_miss_std_diff',\n", + " 'att_freekick_miss_std_h',\n", + " 'att_freekick_target_std_diff',\n", + " 'att_freekick_total_mean_a',\n", + " 'att_freekick_total_mean_diff',\n", + " 'att_freekick_total_mean_h',\n", + " 'att_freekick_total_std_diff',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_left_mean_a',\n", + " 'att_goal_high_left_mean_diff',\n", + " 'att_goal_high_left_std_h',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_high_right_std_diff',\n", + " 'att_goal_low_centre_mean_a',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_goal_low_right_mean_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_post_std_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_total_mean_diff',\n", + " 'att_hd_total_std_h',\n", + " 'att_ibox_blocked_mean_a',\n", + " 'att_ibox_blocked_std_diff',\n", + " 'att_ibox_blocked_std_h',\n", + " 'att_ibox_own_goal_mean_h',\n", + " 'att_ibox_own_goal_std_diff',\n", + " 'att_lf_goal_mean_diff',\n", + " 'att_lf_goal_mean_h',\n", + " 'att_lf_goal_std_h',\n", + " 'att_lg_centre_mean_diff',\n", + " 'att_lg_centre_mean_h',\n", + " 'att_lg_centre_std_a',\n", + " 'att_miss_high_left_std_a',\n", + " 'att_miss_high_left_std_h',\n", + " 'att_miss_right_std_diff',\n", + " 'att_miss_right_std_h',\n", + " 'att_obox_blocked_mean_h',\n", + " 'att_obox_blocked_std_a',\n", + " 'att_obox_goal_mean_h',\n", + " 'att_obox_goal_std_a',\n", + " 'att_obox_goal_std_diff',\n", + " 'att_obox_miss_mean_a',\n", + " 'att_obox_miss_mean_diff',\n", + " 'att_obox_miss_std_a',\n", + " 'att_obox_post_mean_diff',\n", + " 'att_obx_centre_std_a',\n", + " 'att_obx_right_mean_diff',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_one_on_one_std_diff',\n", + " 'att_openplay_mean_h',\n", + " 'att_openplay_std_h',\n", + " 'att_pen_goal_mean_a',\n", + " 'att_pen_goal_mean_h',\n", + " 'att_pen_goal_std_a',\n", + " 'att_post_left_std_a',\n", + " 'att_post_left_std_diff',\n", + " 'att_post_left_std_h',\n", + " 'att_rf_goal_mean_h',\n", + " 'att_rf_target_std_a',\n", + " 'att_rf_total_mean_a',\n", + " 'att_rf_total_std_diff',\n", + " 'att_setpiece_std_a',\n", + " 'att_sv_low_centre_mean_h',\n", + " 'att_sv_low_centre_std_diff',\n", + " 'att_sv_low_right_std_h',\n", + " 'attempts_conceded_ibox_mean_diff',\n", + " 'attempts_conceded_ibox_std_diff',\n", + " 'attempts_ibox_std_a',\n", + " 'attempts_ibox_std_h',\n", + " 'attempts_obox_mean_h',\n", + " 'backward_pass_mean_a',\n", + " 'backward_pass_std_h',\n", + " 'ball_recovery_mean_diff',\n", + " 'bc_miss_div_created_std_h',\n", + " 'bc_miss_div_scored_std_h',\n", + " 'bc_scored_div_created_mean_a',\n", + " 'bc_scored_div_created_mean_diff',\n", + " 'bc_scored_div_created_std_h',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_diff',\n", + " 'big_chance_missed_std_diff',\n", + " 'big_chance_scored_mean_diff',\n", + " 'blocked_cross_mean_a',\n", + " 'blocked_cross_std_a',\n", + " 'challenge_lost_std_a',\n", + " 'challenge_lost_std_diff',\n", + " 'clean_sheet_std_diff',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_std_a',\n", + " 'corner_taken_std_diff',\n", + " 'corners_ratio_mean_h',\n", + " 'crosses_18yard_mean_a',\n", + " 'dispossessed_std_h',\n", + " 'diving_save_mean_h',\n", + " 'diving_save_std_diff',\n", + " 'draw_streak_h',\n", + " 'duel_won_std_a',\n", + " 'effective_clearance_mean_a',\n", + " 'effective_clearance_mean_diff',\n", + " 'effective_head_clearance_mean_h',\n", + " 'error_lead_to_goal_mean_diff',\n", + " 'first_yellow_card_1t_std_diff',\n", + " 'first_yellow_card_std_a',\n", + " 'freekick_cross_std_a',\n", + " 'fwd_pass_std_a',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_deadball_std_h',\n", + " 'goal_assist_intent_norm_mean_h',\n", + " 'goal_assist_intent_norm_std_diff',\n", + " 'goal_assist_intentional_mean_diff',\n", + " 'goal_assist_intentional_mean_h',\n", + " 'goal_assist_mean_a',\n", + " 'goal_assist_mean_h',\n", + " 'goal_assist_openplay_mean_h',\n", + " 'goal_assist_openplay_std_a',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_mean_a',\n", + " 'goal_assist_std_diff',\n", + " 'goal_assist_std_h',\n", + " 'goal_fastbreak_mean_diff',\n", + " 'goal_fastbreak_mean_h',\n", + " 'goal_kicks_div_long_passes_std_diff',\n", + " 'goal_kicks_per_shot_mean_a',\n", + " 'goals_2t_mean_diff',\n", + " 'goals_2t_mean_h',\n", + " 'goals_2t_pct_std_h',\n", + " 'goals_conceded_ibox_mean_h',\n", + " 'goals_conceded_mean_a',\n", + " 'goals_mean_a',\n", + " 'goals_mean_diff',\n", + " 'goals_openplay_mean_a',\n", + " 'goals_openplay_std_h',\n", + " 'goals_std_h',\n", + " 'good_high_claim_mean_a',\n", + " 'good_high_claim_mean_diff',\n", + " 'good_high_claim_mean_h',\n", + " 'hit_woodwork_mean_a',\n", + " 'interceptions_in_box_mean_diff',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_diff',\n", + " 'last_man_tackle_std_a',\n", + " 'left_div_right_foot_goals_mean_a',\n", + " 'leftside_pass_std_diff',\n", + " 'lineup_mean_h',\n", + " 'long_pass_own_to_opp_success_std_diff',\n", + " 'lost_corners_mean_a',\n", + " 'lost_corners_std_diff',\n", + " 'no_foot_goals_ratio_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_over_cards_5.5',\n", + " 'odds_away_over_cards_5.5_a',\n", + " 'odds_away_over_corners_9.5_diff',\n", + " 'odds_away_under_cards_3.5_h',\n", + " 'odds_away_under_corners_6.5_a',\n", + " 'odds_away_under_corners_8.5_a',\n", + " 'odds_home_over_goals_1.5_a',\n", + " 'odds_home_under_cards_4.5_h',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'ontarget_att_assist_std_a',\n", + " 'ontarget_att_assist_std_diff',\n", + " 'open_play_pass_std_a',\n", + " 'outfielder_block_mean_h',\n", + " 'own_goals_std_diff',\n", + " 'own_goals_std_h',\n", + " 'passes_left_div_blocked_pass_std_h',\n", + " 'passes_right_mean_diff',\n", + " 'passes_right_std_a',\n", + " 'passes_right_std_diff',\n", + " 'passes_right_std_h',\n", + " 'pen_area_entries_mean_a',\n", + " 'pen_goals_conceded_std_diff',\n", + " 'penalty_conceded_mean_a',\n", + " 'penalty_faced_mean_diff',\n", + " 'penalty_faced_std_diff',\n", + " 'penalty_save_mean_diff',\n", + " 'penalty_save_mean_h',\n", + " 'penalty_won_mean_a',\n", + " 'penalty_won_std_a',\n", + " 'points_diff',\n", + " 'points_std_a',\n", + " 'points_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'poss_won_mid_3rd_std_a',\n", + " 'post_scoring_att_std_diff',\n", + " 'post_scoring_att_std_h',\n", + " 'prob_squared_over_both_score',\n", + " 'prob_squared_over_goals_2.5',\n", + " 'prob_squared_under_goals_2.5',\n", + " 'prob_squared_under_goals_4.5',\n", + " 'pts_dropped_winning_pos_mean_a',\n", + " 'punches_mean_a',\n", + " 'ranking_h',\n", + " 'ranking_mean_diff',\n", + " 'ratio_over_cards_4.5_a',\n", + " 'ratio_over_corners_8.5_diff',\n", + " 'ratio_over_corners_9.5_a',\n", + " 'ratio_under_corners_10.5_diff',\n", + " 'ratio_under_corners_10.5_h',\n", + " 'ratio_under_corners_11.5_h',\n", + " 'ratio_under_corners_8.5_h',\n", + " 'ratio_under_corners_9.5_diff',\n", + " 'ratio_under_goals_4.5_h',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_under_corners_8.5',\n", + " 'raw_prob_under_goals_4.5',\n", + " 'red_card_1t_mean_a',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_away_ref',\n", + " 'red_card_home_ref',\n", + " 'red_card_std_a',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_std_diff',\n", + " 'rightside_pass_mean_a',\n", + " 'rightside_pass_std_diff',\n", + " 'saves_std_h',\n", + " 'second_yellow_mean_diff',\n", + " 'shots_div_passes_right_std_h',\n", + " 'shots_mul_goals_mean_a',\n", + " 'shots_mul_goals_std_h',\n", + " 'shots_std_diff',\n", + " 'subs_made_mean_h',\n", + " 'successful_fifty_fifty_std_a',\n", + " 'successful_final_third_passes_std_h',\n", + " 'successful_put_through_std_a',\n", + " 'successful_put_through_std_diff',\n", + " 'successful_put_through_std_h',\n", + " 'total_back_zone_pass_mean_a',\n", + " 'total_bets_over_cards_4.5_a',\n", + " 'total_bets_over_cards_4.5_diff',\n", + " 'total_bets_over_cards_5.5_diff',\n", + " 'total_bets_under_cards_4.5_h',\n", + " 'total_bets_under_corners_6.5_diff',\n", + " 'total_bets_under_corners_9.5_h',\n", + " 'total_bets_under_goals_2.5_a',\n", + " 'total_chipped_pass_std_a',\n", + " 'total_clearance_mean_h',\n", + " 'total_cross_nocorner_std_h',\n", + " 'total_expulsions_ref',\n", + " 'total_final_third_passes_std_diff',\n", + " 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_diff',\n", + " 'total_fwd_zone_pass_std_a',\n", + " 'total_fwd_zone_pass_std_diff',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_high_claim_mean_h',\n", + " 'total_high_claim_std_a',\n", + " 'total_high_claim_std_diff',\n", + " 'total_high_claim_std_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_diff',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_keeper_sweeper_std_diff',\n", + " 'total_launches_mean_a',\n", + " 'total_launches_std_h',\n", + " 'total_layoffs_mean_diff',\n", + " 'total_layoffs_std_a',\n", + " 'total_layoffs_std_diff',\n", + " 'total_layoffs_std_h',\n", + " 'total_penalty_match_ref',\n", + " 'total_red_card_1t_ref',\n", + " 'total_red_card_2t_ref',\n", + " 'total_red_card_match_ref',\n", + " 'total_second_yel_card_home_ref',\n", + " 'total_through_ball_mean_a',\n", + " 'total_through_ball_std_a',\n", + " 'total_throws_mean_h',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_throws_std_h',\n", + " 'total_win_pct_over_corners_7.5_diff',\n", + " 'total_win_pct_over_corners_9.5_a',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_under_cards_3.5_diff',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_3.5_h',\n", + " 'total_yel_card_std_a',\n", + " 'win_pct_away_over_cards_6.5_a',\n", + " 'win_pct_away_over_corners_10.5_diff',\n", + " 'win_pct_away_over_corners_8.5_a',\n", + " 'win_pct_away_over_goals_0.5_diff',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_under_both_score_h',\n", + " 'win_pct_away_under_goals_2.5_a',\n", + " 'win_pct_away_under_goals_2.5_diff',\n", + " 'win_pct_home_over_cards_6.5_a',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_cards_4.5_diff',\n", + " 'win_pct_home_under_corners_11.5_h',\n", + " 'win_pct_home_under_corners_8.5_a',\n", + " 'win_pct_home_under_corners_9.5_h',\n", + " 'win_pct_home_under_goals_2.5_diff',\n", + " 'win_pct_home_under_goals_2.5_h',\n", + " 'winner_mean_diff',\n", + " 'winner_std_diff',\n", + " 'winner_std_h',\n", + " 'won_contest_mean_a',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_std_h',\n", + " 'won_tackle_std_a']" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sorted(selected_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "selected_features_save = ['DEF_mean_a',\n", + " 'MED_mean_diff',\n", + " 'acc_corners_intobox_pct_std_a',\n", + " 'accurate_back_zone_pass_std_a',\n", + " 'accurate_chipped_pass_std_diff',\n", + " 'accurate_cross_nocorner_std_diff',\n", + " 'accurate_cross_std_a',\n", + " 'accurate_cross_std_h',\n", + " 'accurate_fwd_zone_pass_mean_diff',\n", + " 'accurate_fwd_zone_pass_std_a',\n", + " 'accurate_fwd_zone_pass_std_h',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_mean_diff',\n", + " 'accurate_keeper_sweeper_mean_h',\n", + " 'accurate_keeper_sweeper_std_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_keeper_throws_std_diff',\n", + " 'accurate_launches_mean_a',\n", + " 'accurate_launches_std_a',\n", + " 'accurate_layoffs_mean_a',\n", + " 'accurate_layoffs_std_a',\n", + " 'accurate_layoffs_std_diff',\n", + " 'accurate_pass_std_a',\n", + " 'accurate_pass_std_diff',\n", + " 'accurate_pull_back_mean_diff',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'accurate_throws_std_a',\n", + " 'accurate_throws_std_diff',\n", + " 'accurate_throws_std_h',\n", + " 'att_assist_openplay_mean_a',\n", + " 'att_bx_right_mean_h',\n", + " 'att_bx_right_std_diff',\n", + " 'att_cmiss_high_mean_h',\n", + " 'att_cmiss_left_std_a',\n", + " 'att_cmiss_left_std_h',\n", + " 'att_corner_mean_a',\n", + " 'att_corner_ratio_mean_a',\n", + " 'att_fastbreak_std_h',\n", + " 'att_freekick_goal_std_diff',\n", + " 'att_freekick_miss_mean_h',\n", + " 'att_freekick_miss_std_a',\n", + " 'att_freekick_miss_std_diff',\n", + " 'att_freekick_miss_std_h',\n", + " 'att_freekick_target_std_diff',\n", + " 'att_freekick_total_mean_a',\n", + " 'att_freekick_total_mean_diff',\n", + " 'att_freekick_total_mean_h',\n", + " 'att_freekick_total_std_diff',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_left_mean_a',\n", + " 'att_goal_high_left_mean_diff',\n", + " 'att_goal_high_left_std_h',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_high_right_std_diff',\n", + " 'att_goal_low_centre_mean_a',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_goal_low_right_mean_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_post_std_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_total_mean_diff',\n", + " 'att_hd_total_std_h',\n", + " 'att_ibox_blocked_mean_a',\n", + " 'att_ibox_blocked_std_diff',\n", + " 'att_ibox_blocked_std_h',\n", + " 'att_ibox_own_goal_mean_h',\n", + " 'att_ibox_own_goal_std_diff',\n", + " 'att_lf_goal_mean_diff',\n", + " 'att_lf_goal_mean_h',\n", + " 'att_lf_goal_std_h',\n", + " 'att_lg_centre_mean_diff',\n", + " 'att_lg_centre_mean_h',\n", + " 'att_lg_centre_std_a',\n", + " 'att_miss_high_left_std_a',\n", + " 'att_miss_high_left_std_h',\n", + " 'att_miss_right_std_diff',\n", + " 'att_miss_right_std_h',\n", + " 'att_obox_blocked_mean_h',\n", + " 'att_obox_blocked_std_a',\n", + " 'att_obox_goal_mean_h',\n", + " 'att_obox_goal_std_a',\n", + " 'att_obox_goal_std_diff',\n", + " 'att_obox_miss_mean_a',\n", + " 'att_obox_miss_mean_diff',\n", + " 'att_obox_miss_std_a',\n", + " 'att_obox_post_mean_diff',\n", + " 'att_obx_centre_std_a',\n", + " 'att_obx_right_mean_diff',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_one_on_one_std_diff',\n", + " 'att_openplay_mean_h',\n", + " 'att_openplay_std_h',\n", + " 'att_pen_goal_mean_a',\n", + " 'att_pen_goal_mean_h',\n", + " 'att_pen_goal_std_a',\n", + " 'att_post_left_std_a',\n", + " 'att_post_left_std_diff',\n", + " 'att_post_left_std_h',\n", + " 'att_rf_goal_mean_h',\n", + " 'att_rf_target_std_a',\n", + " 'att_rf_total_mean_a',\n", + " 'att_rf_total_std_diff',\n", + " 'att_setpiece_std_a',\n", + " 'att_sv_low_centre_mean_h',\n", + " 'att_sv_low_centre_std_diff',\n", + " 'att_sv_low_right_std_h',\n", + " 'attempts_conceded_ibox_mean_diff',\n", + " 'attempts_conceded_ibox_std_diff',\n", + " 'attempts_ibox_std_a',\n", + " 'attempts_ibox_std_h',\n", + " 'attempts_obox_mean_h',\n", + " 'backward_pass_mean_a',\n", + " 'backward_pass_std_h',\n", + " 'ball_recovery_mean_diff',\n", + " 'bc_miss_div_created_std_h',\n", + " 'bc_miss_div_scored_std_h',\n", + " 'bc_scored_div_created_mean_a',\n", + " 'bc_scored_div_created_mean_diff',\n", + " 'bc_scored_div_created_std_h',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_diff',\n", + " 'big_chance_missed_std_diff',\n", + " 'big_chance_scored_mean_diff',\n", + " 'blocked_cross_mean_a',\n", + " 'blocked_cross_std_a',\n", + " 'challenge_lost_std_a',\n", + " 'challenge_lost_std_diff',\n", + " 'clean_sheet_std_diff',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_std_a',\n", + " 'corner_taken_std_diff',\n", + " 'corners_ratio_mean_h',\n", + " 'crosses_18yard_mean_a',\n", + " 'dispossessed_std_h',\n", + " 'diving_save_mean_h',\n", + " 'diving_save_std_diff',\n", + " 'draw_streak_h',\n", + " 'duel_won_std_a',\n", + " 'effective_clearance_mean_a',\n", + " 'effective_clearance_mean_diff',\n", + " 'effective_head_clearance_mean_h',\n", + " 'error_lead_to_goal_mean_diff',\n", + " 'first_yellow_card_1t_std_diff',\n", + " 'first_yellow_card_std_a',\n", + " 'freekick_cross_std_a',\n", + " 'fwd_pass_std_a',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_deadball_std_h',\n", + " 'goal_assist_intent_norm_mean_h',\n", + " 'goal_assist_intent_norm_std_diff',\n", + " 'goal_assist_intentional_mean_diff',\n", + " 'goal_assist_intentional_mean_h',\n", + " 'goal_assist_mean_a',\n", + " 'goal_assist_mean_h',\n", + " 'goal_assist_openplay_mean_h',\n", + " 'goal_assist_openplay_std_a',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_mean_a',\n", + " 'goal_assist_std_diff',\n", + " 'goal_assist_std_h',\n", + " 'goal_fastbreak_mean_diff',\n", + " 'goal_fastbreak_mean_h',\n", + " 'goal_kicks_div_long_passes_std_diff',\n", + " 'goal_kicks_per_shot_mean_a',\n", + " 'goals_2t_mean_diff',\n", + " 'goals_2t_mean_h',\n", + " 'goals_2t_pct_std_h',\n", + " 'goals_conceded_ibox_mean_h',\n", + " 'goals_conceded_mean_a',\n", + " 'goals_mean_a',\n", + " 'goals_mean_diff',\n", + " 'goals_openplay_mean_a',\n", + " 'goals_openplay_std_h',\n", + " 'goals_std_h',\n", + " 'good_high_claim_mean_a',\n", + " 'good_high_claim_mean_diff',\n", + " 'good_high_claim_mean_h',\n", + " 'hit_woodwork_mean_a',\n", + " 'interceptions_in_box_mean_diff',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_diff',\n", + " 'last_man_tackle_std_a',\n", + " 'left_div_right_foot_goals_mean_a',\n", + " 'leftside_pass_std_diff',\n", + " 'lineup_mean_h',\n", + " 'long_pass_own_to_opp_success_std_diff',\n", + " 'lost_corners_mean_a',\n", + " 'lost_corners_std_diff',\n", + " 'no_foot_goals_ratio_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_over_cards_5.5',\n", + " 'odds_away_over_cards_5.5_a',\n", + " 'odds_away_over_corners_9.5_diff',\n", + " 'odds_away_under_cards_3.5_h',\n", + " 'odds_away_under_corners_6.5_a',\n", + " 'odds_away_under_corners_8.5_a',\n", + " 'odds_home_over_goals_1.5_a',\n", + " 'odds_home_under_cards_4.5_h',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'ontarget_att_assist_std_a',\n", + " 'ontarget_att_assist_std_diff',\n", + " 'open_play_pass_std_a',\n", + " 'outfielder_block_mean_h',\n", + " 'own_goals_std_diff',\n", + " 'own_goals_std_h',\n", + " 'passes_left_div_blocked_pass_std_h',\n", + " 'passes_right_mean_diff',\n", + " 'passes_right_std_a',\n", + " 'passes_right_std_diff',\n", + " 'passes_right_std_h',\n", + " 'pen_area_entries_mean_a',\n", + " 'pen_goals_conceded_std_diff',\n", + " 'penalty_conceded_mean_a',\n", + " 'penalty_faced_mean_diff',\n", + " 'penalty_faced_std_diff',\n", + " 'penalty_save_mean_diff',\n", + " 'penalty_save_mean_h',\n", + " 'penalty_won_mean_a',\n", + " 'penalty_won_std_a',\n", + " 'points_diff',\n", + " 'points_std_a',\n", + " 'points_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'poss_won_mid_3rd_std_a',\n", + " 'post_scoring_att_std_diff',\n", + " 'post_scoring_att_std_h',\n", + " 'prob_squared_over_both_score',\n", + " 'prob_squared_over_goals_2.5',\n", + " 'prob_squared_under_goals_2.5',\n", + " 'prob_squared_under_goals_4.5',\n", + " 'pts_dropped_winning_pos_mean_a',\n", + " 'punches_mean_a',\n", + " 'ranking_h',\n", + " 'ranking_mean_diff',\n", + " 'ratio_over_cards_4.5_a',\n", + " 'ratio_over_corners_8.5_diff',\n", + " 'ratio_over_corners_9.5_a',\n", + " 'ratio_under_corners_10.5_diff',\n", + " 'ratio_under_corners_10.5_h',\n", + " 'ratio_under_corners_11.5_h',\n", + " 'ratio_under_corners_8.5_h',\n", + " 'ratio_under_corners_9.5_diff',\n", + " 'ratio_under_goals_4.5_h',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_under_corners_8.5',\n", + " 'raw_prob_under_goals_4.5',\n", + " 'red_card_1t_mean_a',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_away_ref',\n", + " 'red_card_home_ref',\n", + " 'red_card_std_a',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_std_diff',\n", + " 'rightside_pass_mean_a',\n", + " 'rightside_pass_std_diff',\n", + " 'saves_std_h',\n", + " 'second_yellow_mean_diff',\n", + " 'shots_div_passes_right_std_h',\n", + " 'shots_mul_goals_mean_a',\n", + " 'shots_mul_goals_std_h',\n", + " 'shots_std_diff',\n", + " 'subs_made_mean_h',\n", + " 'successful_fifty_fifty_std_a',\n", + " 'successful_final_third_passes_std_h',\n", + " 'successful_put_through_std_a',\n", + " 'successful_put_through_std_diff',\n", + " 'successful_put_through_std_h',\n", + " 'total_back_zone_pass_mean_a',\n", + " 'total_bets_over_cards_4.5_a',\n", + " 'total_bets_over_cards_4.5_diff',\n", + " 'total_bets_over_cards_5.5_diff',\n", + " 'total_bets_under_cards_4.5_h',\n", + " 'total_bets_under_corners_6.5_diff',\n", + " 'total_bets_under_corners_9.5_h',\n", + " 'total_bets_under_goals_2.5_a',\n", + " 'total_chipped_pass_std_a',\n", + " 'total_clearance_mean_h',\n", + " 'total_cross_nocorner_std_h',\n", + " 'total_expulsions_ref',\n", + " 'total_final_third_passes_std_diff',\n", + " 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_diff',\n", + " 'total_fwd_zone_pass_std_a',\n", + " 'total_fwd_zone_pass_std_diff',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_high_claim_mean_h',\n", + " 'total_high_claim_std_a',\n", + " 'total_high_claim_std_diff',\n", + " 'total_high_claim_std_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_diff',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_keeper_sweeper_std_diff',\n", + " 'total_launches_mean_a',\n", + " 'total_launches_std_h',\n", + " 'total_layoffs_mean_diff',\n", + " 'total_layoffs_std_a',\n", + " 'total_layoffs_std_diff',\n", + " 'total_layoffs_std_h',\n", + " 'total_penalty_match_ref',\n", + " 'total_red_card_1t_ref',\n", + " 'total_red_card_2t_ref',\n", + " 'total_red_card_match_ref',\n", + " 'total_second_yel_card_home_ref',\n", + " 'total_through_ball_mean_a',\n", + " 'total_through_ball_std_a',\n", + " 'total_throws_mean_h',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_throws_std_h',\n", + " 'total_win_pct_over_corners_7.5_diff',\n", + " 'total_win_pct_over_corners_9.5_a',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_under_cards_3.5_diff',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_3.5_h',\n", + " 'total_yel_card_std_a',\n", + " 'win_pct_away_over_cards_6.5_a',\n", + " 'win_pct_away_over_corners_10.5_diff',\n", + " 'win_pct_away_over_corners_8.5_a',\n", + " 'win_pct_away_over_goals_0.5_diff',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_under_both_score_h',\n", + " 'win_pct_away_under_goals_2.5_a',\n", + " 'win_pct_away_under_goals_2.5_diff',\n", + " 'win_pct_home_over_cards_6.5_a',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_cards_4.5_diff',\n", + " 'win_pct_home_under_corners_11.5_h',\n", + " 'win_pct_home_under_corners_8.5_a',\n", + " 'win_pct_home_under_corners_9.5_h',\n", + " 'win_pct_home_under_goals_2.5_diff',\n", + " 'win_pct_home_under_goals_2.5_h',\n", + " 'winner_mean_diff',\n", + " 'winner_std_diff',\n", + " 'winner_std_h',\n", + " 'won_contest_mean_a',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_std_h',\n", + " 'won_tackle_std_a']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### new imports " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from pathlib import Path\n", + "import os\n", + "\n", + "from ml_bets.constants import FEATURES_PATH\n", + "from ml_bets.features.features import Features\n", + "from ml_bets.modeling.match_model import PipelineDatasets, run_pycaret_setup\n", + "#from featsel.feature_selection import FeatureSelection\n", + "\n", + "from pycaret.utils import check_metric\n", + "from pycaret.classification import (add_metric, calibrate_model, optimize_threshold,\n", + " create_model,\n", + " finalize_model,\n", + " optimize_threshold, \n", + " save_model,\n", + " compare_models, \n", + " evaluate_model,\n", + " get_config,\n", + " setup,\n", + " tune_model,\n", + " predict_model,\n", + ")\n", + "\n", + "from ml_bets.supplementary.functions import IGNORE_FEATURES\n", + "from ml_bets.research.datasets import create_dataset\n", + "from ml_bets.features.names.goals import GOALS_FEATURES, NEW_FEATURES" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from ml_bets.research.tips import calibrate_tips, tips_from_model, combine_tips, predict_dataset, compose_tips, get_tip_probs" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "ix = np.logical_and(feats.matches[\"date\"].dt.month > 10,\n", + " feats.matches[\"competition\"].isin({\"mexican_primera\", 'us_major_league_soccer'}))\n", + "index = feats.matches[~ix].index" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def setup_dataset(test_date):\n", + " ds = create_dataset(target=target,\n", + " test_date=test_date,\n", + " features=feats,\n", + " odds_features=True,\n", + " include_std=True,\n", + " test_weeks=4,\n", + " ignore_features=IGNORE_FEATURES,\n", + " drop_future_matches=False,\n", + " )\n", + " train_data = ds.train_data.copy()#[ds.train_data.index.map(lambda x: \"us_major_league_soccer\" not in x and \"mexican\" not in x)]\n", + " train_data.drop(columns=[\"hour_rank\", \"hour_before_16\", \"is_weekend\"], inplace=True)\n", + " train_data = train_data[train_data.index.isin(index)][list(set(selected_features)) + [target]].copy()#.reset_index(drop=True)\n", + " test_data = ds.test_set[ds.test_set.index.isin(index)][list(set(selected_features)) + [target]].copy()#.reset_index(drop=True)\n", + " val_data = ds.val_set[ds.val_set.index.isin(index)].copy()\n", + " setup_kwargs = dict(\n", + " preprocess=True,\n", + " test_data=test_data[train_data.columns.tolist()],#.dropna(),\n", + " #numeric_features=[x for x in train_data.columns.tolist() if x != target],\n", + " #custom_pipeline=loaded,\n", + " #train_size=0.75,\n", + " session_id=123,\n", + " normalize=True,\n", + " normalize_method=\"robust\",\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.8,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " #ignore_features=ignore_features,\n", + " fold_strategy=\"stratifiedkfold\",#\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=4,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.5,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"kernel\",\n", + " pca_components=50,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.05,\n", + " trigonometry_features=False,\n", + " remove_outliers=True,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.05,\n", + " fix_imbalance=True,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " )\n", + " _ = setup(data=train_data, target=target, **setup_kwargs)\n", + " return train_data, test_data, val_data, ds" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "train_data, test_data, val_data, ds = setup_dataset(\"4-Dec-2021\")" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "from pycaret.classification import stack_models, ensemble_model, blend_models\n", + "def train_ensemble():\n", + " top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"et\", \"svm\"],\n", + " verbose=True,\n", + " )\n", + " tuned_models = [tune_model(model, optimize=\"AUC\", choose_better=True, n_iter=50, search_library=\"optuna\") for model in top_models]\n", + " cali = [calibrate_model(tuned, method=\"sigmoid\", calibrate_fold=4) for tuned in tuned_models]\n", + " blend = blend_models(cali)\n", + " opti = tune_model(blend, optimize=\"Precision\", choose_better=True, n_iter=50, search_library=\"optuna\")\n", + " return opti, cali, tuned_models, blend" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Accuracy AUC Recall Prec. F1 Kappa MCC
00.62080.00000.64040.63570.63800.23990.2399
10.60490.00000.62320.62160.62240.20810.2081
20.64220.00000.64040.66330.65160.28410.2843
30.59970.00000.52460.64350.57800.20480.2087
Mean0.61690.00000.60710.64100.62250.23420.2353
SD0.01650.00000.04820.01500.02770.03190.0311
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "ename": "TypeError", + "evalue": "calibrate_model() got an unexpected keyword argument 'calibrate_fold'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mopti_model\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcali_model\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtune_model\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mblend_model\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtrain_ensemble\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32m\u001b[0m in \u001b[0;36mtrain_ensemble\u001b[1;34m()\u001b[0m\n\u001b[0;32m 8\u001b[0m )\n\u001b[0;32m 9\u001b[0m \u001b[0mtuned_models\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mtune_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moptimize\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"AUC\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mchoose_better\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mn_iter\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m50\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msearch_library\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"optuna\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mmodel\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mtop_models\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m \u001b[0mcali\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mcalibrate_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtuned\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmethod\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"sigmoid\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcalibrate_fold\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mtuned\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mtuned_models\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 11\u001b[0m \u001b[0mblend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mblend_models\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcali\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mopti\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtune_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mblend\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moptimize\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"Precision\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mchoose_better\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mn_iter\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m50\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msearch_library\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"optuna\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m(.0)\u001b[0m\n\u001b[0;32m 8\u001b[0m )\n\u001b[0;32m 9\u001b[0m \u001b[0mtuned_models\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mtune_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moptimize\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"AUC\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mchoose_better\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mn_iter\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m50\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msearch_library\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"optuna\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mmodel\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mtop_models\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m \u001b[0mcali\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mcalibrate_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtuned\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmethod\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"sigmoid\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcalibrate_fold\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mtuned\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mtuned_models\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 11\u001b[0m \u001b[0mblend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mblend_models\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcali\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mopti\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtune_model\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mblend\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moptimize\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"Precision\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mchoose_better\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mn_iter\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m50\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msearch_library\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m\"optuna\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mTypeError\u001b[0m: calibrate_model() got an unexpected keyword argument 'calibrate_fold'" + ] + } + ], + "source": [ + "opti_model, cali_model, tune_model, blend_model = train_ensemble()" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC TT (Sec)
lrLogistic Regression0.58310.61610.59370.60300.59710.16520.16580.6300
svmSVM - Linear Kernel0.57800.00000.59750.60370.58450.15440.16560.2050
ridgeRidge Classifier0.58250.00000.59370.60180.59660.16390.16450.2000
ldaLinear Discriminant Analysis0.58190.61070.59620.60030.59720.16240.16290.2100
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"svm\"],\n", + " verbose=True,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(top_models[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feature selection (adding triplet)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(181,\n", + " 583,\n", + " ['ATT_h_mul_shots_mul_goals_mean_diff',\n", + " 'DEF_h_mul_shots_mul_goals_mean_diff',\n", + " 'DEF_mean_a',\n", + " 'DEF_mean_diff',\n", + " 'DEF_mean_h',\n", + " 'MED_a',\n", + " 'MED_diff',\n", + " 'MED_h',\n", + " 'MED_mean_a',\n", + " 'MED_mean_diff',\n", + " 'MED_mean_h',\n", + " 'MED_std_a',\n", + " 'MED_std_diff',\n", + " 'MED_std_h',\n", + " 'accurate_cross_nocorner_std_a',\n", + " 'accurate_cross_nocorner_std_diff',\n", + " 'accurate_cross_nocorner_std_h',\n", + " 'accurate_cross_std_a',\n", + " 'accurate_cross_std_diff',\n", + " 'accurate_cross_std_h',\n", + " 'accurate_fwd_zone_pass_mean_a',\n", + " 'accurate_fwd_zone_pass_mean_diff',\n", + " 'accurate_fwd_zone_pass_mean_h',\n", + " 'accurate_fwd_zone_pass_std_a',\n", + " 'accurate_fwd_zone_pass_std_diff',\n", + " 'accurate_fwd_zone_pass_std_h',\n", + " 'accurate_goal_kicks_std_a',\n", + " 'accurate_goal_kicks_std_diff',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_mean_diff',\n", + " 'accurate_keeper_sweeper_mean_h',\n", + " 'accurate_keeper_sweeper_std_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_launches_mean_a',\n", + " 'accurate_launches_mean_diff',\n", + " 'accurate_launches_mean_h',\n", + " 'accurate_layoffs_mean_a',\n", + " 'accurate_layoffs_mean_diff',\n", + " 'accurate_layoffs_mean_h',\n", + " 'accurate_layoffs_std_a',\n", + " 'accurate_layoffs_std_diff',\n", + " 'accurate_layoffs_std_h',\n", + " 'accurate_pass_std_a',\n", + " 'accurate_pass_std_diff',\n", + " 'accurate_pass_std_h',\n", + " 'accurate_through_ball_mean_a',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'accurate_through_ball_mean_h',\n", + " 'accurate_throws_std_a',\n", + " 'accurate_throws_std_diff',\n", + " 'accurate_throws_std_h',\n", + " 'att_assist_openplay_mean_a',\n", + " 'att_assist_openplay_mean_diff',\n", + " 'att_assist_openplay_mean_h',\n", + " 'att_corner_ratio_mean_a',\n", + " 'att_corner_ratio_mean_diff',\n", + " 'att_corner_ratio_mean_h',\n", + " 'att_freekick_goal_std_a',\n", + " 'att_freekick_goal_std_diff',\n", + " 'att_freekick_goal_std_h',\n", + " 'att_freekick_miss_mean_a',\n", + " 'att_freekick_miss_mean_diff',\n", + " 'att_freekick_miss_mean_h',\n", + " 'att_freekick_miss_std_a',\n", + " 'att_freekick_miss_std_diff',\n", + " 'att_freekick_miss_std_h',\n", + " 'att_freekick_total_mean_a',\n", + " 'att_freekick_total_mean_diff',\n", + " 'att_freekick_total_mean_h',\n", + " 'att_goal_high_centre_mean_a',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_mean_h',\n", + " 'att_goal_high_centre_std_a',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_centre_std_h',\n", + " 'att_goal_high_left_mean_a',\n", + " 'att_goal_high_left_mean_diff',\n", + " 'att_goal_high_left_mean_h',\n", + " 'att_goal_high_left_std_a',\n", + " 'att_goal_high_left_std_diff',\n", + " 'att_goal_high_left_std_h',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_high_right_std_diff',\n", + " 'att_goal_high_right_std_h',\n", + " 'att_goal_low_centre_mean_a',\n", + " 'att_goal_low_centre_mean_diff',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_diff',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_goal_low_right_mean_a',\n", + " 'att_goal_low_right_mean_diff',\n", + " 'att_goal_low_right_mean_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_diff',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_target_mean_diff',\n", + " 'att_hd_target_mean_h',\n", + " 'att_ibox_own_goal_std_a',\n", + " 'att_ibox_own_goal_std_diff',\n", + " 'att_ibox_own_goal_std_h',\n", + " 'att_lf_goal_mean_a',\n", + " 'att_lf_goal_mean_diff',\n", + " 'att_lf_goal_mean_h',\n", + " 'att_lf_goal_std_a',\n", + " 'att_lf_goal_std_diff',\n", + " 'att_lf_goal_std_h',\n", + " 'att_lg_centre_mean_a',\n", + " 'att_lg_centre_mean_diff',\n", + " 'att_lg_centre_mean_h',\n", + " 'att_miss_high_left_std_a',\n", + " 'att_miss_high_left_std_diff',\n", + " 'att_miss_high_left_std_h',\n", + " 'att_miss_right_std_a',\n", + " 'att_miss_right_std_diff',\n", + " 'att_miss_right_std_h',\n", + " 'att_obox_blocked_mean_a',\n", + " 'att_obox_blocked_mean_diff',\n", + " 'att_obox_blocked_mean_h',\n", + " 'att_obox_goal_mean_a',\n", + " 'att_obox_goal_mean_diff',\n", + " 'att_obox_goal_mean_h',\n", + " 'att_obox_goal_std_a',\n", + " 'att_obox_goal_std_diff',\n", + " 'att_obox_goal_std_h',\n", + " 'att_obox_miss_mean_a',\n", + " 'att_obox_miss_mean_diff',\n", + " 'att_obox_miss_mean_h',\n", + " 'att_obox_post_mean_a',\n", + " 'att_obox_post_mean_diff',\n", + " 'att_obox_post_mean_h',\n", + " 'att_obx_right_mean_a',\n", + " 'att_obx_right_mean_diff',\n", + " 'att_obx_right_mean_h',\n", + " 'att_obxd_right_mean_a',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_mean_h',\n", + " 'att_obxd_right_std_a',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_obxd_right_std_h',\n", + " 'att_openplay_mean_a',\n", + " 'att_openplay_mean_diff',\n", + " 'att_openplay_mean_h',\n", + " 'att_pen_goal_mean_a',\n", + " 'att_pen_goal_mean_diff',\n", + " 'att_pen_goal_mean_h',\n", + " 'att_post_left_mean_a',\n", + " 'att_post_left_mean_diff',\n", + " 'att_post_left_mean_h',\n", + " 'att_post_left_std_a',\n", + " 'att_post_left_std_diff',\n", + " 'att_post_left_std_h',\n", + " 'attempts_conceded_ibox_std_a',\n", + " 'attempts_conceded_ibox_std_diff',\n", + " 'attempts_conceded_ibox_std_h',\n", + " 'attempts_conceded_obox_std_a',\n", + " 'attempts_conceded_obox_std_diff',\n", + " 'attempts_conceded_obox_std_h',\n", + " 'attempts_obox_mean_a',\n", + " 'attempts_obox_mean_diff',\n", + " 'attempts_obox_mean_h',\n", + " 'bc_miss_div_scored_std_a',\n", + " 'bc_miss_div_scored_std_diff',\n", + " 'bc_miss_div_scored_std_h',\n", + " 'big_chance_created_mean_a',\n", + " 'big_chance_created_mean_diff',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_a',\n", + " 'big_chance_created_std_diff',\n", + " 'big_chance_created_std_h',\n", + " 'big_chance_missed_std_a',\n", + " 'big_chance_missed_std_diff',\n", + " 'big_chance_missed_std_h',\n", + " 'big_chance_scored_mean_a',\n", + " 'big_chance_scored_mean_diff',\n", + " 'big_chance_scored_mean_diff_mul_total_fwd_zone_pass_mean_diff',\n", + " 'big_chance_scored_mean_h',\n", + " 'blocked_cross_mean_a',\n", + " 'blocked_cross_mean_diff',\n", + " 'blocked_cross_mean_h',\n", + " 'contentious_decision_mean_a',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_mean_h',\n", + " 'contentious_decision_std_a',\n", + " 'contentious_decision_std_diff',\n", + " 'contentious_decision_std_h',\n", + " 'corner_taken_std_mul_att_corner_ratio_mean_diffs',\n", + " 'corners_ratio_mean_a',\n", + " 'corners_ratio_mean_diff',\n", + " 'corners_ratio_mean_h',\n", + " 'defender_goals_mean_a',\n", + " 'defender_goals_mean_diff',\n", + " 'defender_goals_mean_h',\n", + " 'diving_save_std_a',\n", + " 'diving_save_std_diff',\n", + " 'diving_save_std_h',\n", + " 'effective_clearance_mean_a',\n", + " 'effective_clearance_mean_diff',\n", + " 'effective_clearance_mean_h',\n", + " 'effective_head_clearance_mean_a',\n", + " 'effective_head_clearance_mean_diff',\n", + " 'effective_head_clearance_mean_h',\n", + " 'first_yellow_card_std_a',\n", + " 'first_yellow_card_std_diff',\n", + " 'first_yellow_card_std_h',\n", + " 'forward_goals_mean_a',\n", + " 'forward_goals_mean_diff',\n", + " 'forward_goals_mean_h',\n", + " 'fwd_pass_div_long_pass_own_to_opp_success_std_a',\n", + " 'fwd_pass_div_long_pass_own_to_opp_success_std_diff',\n", + " 'fwd_pass_div_long_pass_own_to_opp_success_std_h',\n", + " 'goal_assist_deadball_mean_a',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_deadball_mean_h',\n", + " 'goal_assist_deadball_std_a',\n", + " 'goal_assist_deadball_std_diff',\n", + " 'goal_assist_deadball_std_h',\n", + " 'goal_assist_intent_norm_mean_a',\n", + " 'goal_assist_intent_norm_mean_diff',\n", + " 'goal_assist_intent_norm_mean_h',\n", + " 'goal_assist_intentional_mean_a',\n", + " 'goal_assist_intentional_mean_diff',\n", + " 'goal_assist_intentional_mean_h',\n", + " 'goal_assist_intentional_std_a',\n", + " 'goal_assist_intentional_std_diff',\n", + " 'goal_assist_intentional_std_h',\n", + " 'goal_assist_mean_a',\n", + " 'goal_assist_mean_diff',\n", + " 'goal_assist_mean_h',\n", + " 'goal_assist_openplay_std_a',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_mean_a',\n", + " 'goal_assist_setplay_mean_diff',\n", + " 'goal_assist_setplay_mean_h',\n", + " 'goal_assist_std_a',\n", + " 'goal_assist_std_diff',\n", + " 'goal_assist_std_h',\n", + " 'goal_fastbreak_mean_a',\n", + " 'goal_fastbreak_mean_diff',\n", + " 'goal_fastbreak_mean_h',\n", + " 'goal_kicks_per_shot_mean_a',\n", + " 'goal_kicks_per_shot_mean_diff',\n", + " 'goal_kicks_per_shot_mean_h',\n", + " 'goals_2t_mean_a',\n", + " 'goals_2t_mean_diff',\n", + " 'goals_2t_mean_h',\n", + " 'goals_mean_a',\n", + " 'goals_mean_diff',\n", + " 'goals_mean_h',\n", + " 'goals_openplay_mean_a',\n", + " 'goals_openplay_mean_diff',\n", + " 'goals_openplay_mean_h',\n", + " 'high_to_low_goals_mean_a',\n", + " 'high_to_low_goals_mean_diff',\n", + " 'high_to_low_goals_mean_h',\n", + " 'imp_prob_over_goals_0.5_a',\n", + " 'imp_prob_over_goals_0.5_diff',\n", + " 'imp_prob_over_goals_0.5_h',\n", + " 'imp_prob_over_goals_1.5_a',\n", + " 'imp_prob_over_goals_1.5_diff',\n", + " 'imp_prob_over_goals_1.5_h',\n", + " 'imp_prob_over_goals_2.5_a',\n", + " 'imp_prob_over_goals_2.5_diff',\n", + " 'imp_prob_over_goals_2.5_h',\n", + " 'imp_prob_over_goals_3.5_a',\n", + " 'imp_prob_over_goals_3.5_diff',\n", + " 'imp_prob_over_goals_3.5_h',\n", + " 'imp_prob_over_goals_4.5_a',\n", + " 'imp_prob_over_goals_4.5_diff',\n", + " 'imp_prob_over_goals_4.5_h',\n", + " 'imp_prob_under_goals_0.5_a',\n", + " 'imp_prob_under_goals_0.5_diff',\n", + " 'imp_prob_under_goals_0.5_h',\n", + " 'imp_prob_under_goals_1.5_a',\n", + " 'imp_prob_under_goals_1.5_diff',\n", + " 'imp_prob_under_goals_1.5_h',\n", + " 'imp_prob_under_goals_2.5_a',\n", + " 'imp_prob_under_goals_2.5_diff',\n", + " 'imp_prob_under_goals_2.5_h',\n", + " 'imp_prob_under_goals_3.5_a',\n", + " 'imp_prob_under_goals_3.5_diff',\n", + " 'imp_prob_under_goals_3.5_h',\n", + " 'imp_prob_under_goals_4.5_a',\n", + " 'imp_prob_under_goals_4.5_diff',\n", + " 'imp_prob_under_goals_4.5_h',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_a',\n", + " 'last_man_tackle_mean_diff',\n", + " 'last_man_tackle_mean_h',\n", + " 'last_man_tackle_std_a',\n", + " 'last_man_tackle_std_diff',\n", + " 'last_man_tackle_std_h',\n", + " 'left_div_right_foot_goals_mean_a',\n", + " 'left_div_right_foot_goals_mean_diff',\n", + " 'left_div_right_foot_goals_mean_h',\n", + " 'leftside_pass_div_accurate_pass_std_a',\n", + " 'leftside_pass_div_accurate_pass_std_diff',\n", + " 'leftside_pass_div_accurate_pass_std_h',\n", + " 'leftside_pass_mean_a',\n", + " 'leftside_pass_mean_diff',\n", + " 'leftside_pass_mean_h',\n", + " 'long_pass_own_to_opp_success_std_a',\n", + " 'long_pass_own_to_opp_success_std_diff',\n", + " 'long_pass_own_to_opp_success_std_h',\n", + " 'lost_corners_mean_a',\n", + " 'lost_corners_mean_diff',\n", + " 'lost_corners_mean_h',\n", + " 'midfielder_goals_mean_a',\n", + " 'midfielder_goals_mean_diff',\n", + " 'midfielder_goals_mean_h',\n", + " 'no_foot_goals_ratio_mean_a',\n", + " 'no_foot_goals_ratio_mean_diff',\n", + " 'no_foot_goals_ratio_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_diff',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_over_corners_11.5',\n", + " 'odd_ratio_over_corners_9.5',\n", + " 'odd_ratio_under_corners_10.5',\n", + " 'odd_ratio_under_goals_1.5',\n", + " 'odd_ratio_under_goals_2.5',\n", + " 'odd_ratio_under_goals_3.5',\n", + " 'odd_ratio_under_goals_4.5',\n", + " 'odd_ratio_under_goals_4.5',\n", + " 'odds_away_over_cards_4.5_a',\n", + " 'odds_away_over_cards_4.5_diff',\n", + " 'odds_away_over_cards_4.5_h',\n", + " 'odds_away_over_cards_5.5_a',\n", + " 'odds_away_over_cards_5.5_diff',\n", + " 'odds_away_over_cards_5.5_h',\n", + " 'odds_away_under_cards_3.5_a',\n", + " 'odds_away_under_cards_3.5_diff',\n", + " 'odds_away_under_cards_3.5_h',\n", + " 'odds_home_under_cards_5.5_a',\n", + " 'odds_home_under_cards_5.5_diff',\n", + " 'odds_home_under_cards_5.5_h',\n", + " 'odds_home_under_goals_0.5_a',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'odds_home_under_goals_0.5_h',\n", + " 'ontarget_att_assist_mean_a',\n", + " 'ontarget_att_assist_mean_diff',\n", + " 'ontarget_att_assist_mean_h',\n", + " 'own_goals_mean_a',\n", + " 'own_goals_mean_diff',\n", + " 'own_goals_mean_h',\n", + " 'own_goals_std_a',\n", + " 'own_goals_std_diff',\n", + " 'own_goals_std_h',\n", + " 'passes_left_mean_a',\n", + " 'passes_left_mean_diff',\n", + " 'passes_left_mean_h',\n", + " 'passes_right_mean_a',\n", + " 'passes_right_mean_diff',\n", + " 'passes_right_mean_h',\n", + " 'passes_right_std_a',\n", + " 'passes_right_std_diff',\n", + " 'passes_right_std_h',\n", + " 'pen_goals_conceded_std_a',\n", + " 'pen_goals_conceded_std_diff',\n", + " 'pen_goals_conceded_std_h',\n", + " 'penalty_conceded_mean_a',\n", + " 'penalty_conceded_mean_diff',\n", + " 'penalty_conceded_mean_h',\n", + " 'penalty_faced_std_a',\n", + " 'penalty_faced_std_diff',\n", + " 'penalty_faced_std_h',\n", + " 'penalty_save_std_a',\n", + " 'penalty_save_std_diff',\n", + " 'penalty_save_std_h',\n", + " 'points_a',\n", + " 'points_diff',\n", + " 'points_h',\n", + " 'points_mean_a',\n", + " 'points_mean_diff',\n", + " 'points_mean_h',\n", + " 'points_std_a',\n", + " 'points_std_diff',\n", + " 'points_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'prob_over_goals_1.5',\n", + " 'prob_over_goals_2.5',\n", + " 'prob_over_goals_3.5',\n", + " 'prob_over_goals_4.5',\n", + " 'prob_squared_over_goals_1.5',\n", + " 'prob_squared_over_goals_2.5',\n", + " 'prob_squared_over_goals_3.5',\n", + " 'prob_squared_over_goals_4.5',\n", + " 'prob_squared_under_goals_1.5',\n", + " 'prob_squared_under_goals_2.5',\n", + " 'prob_squared_under_goals_3.5',\n", + " 'prob_squared_under_goals_4.5',\n", + " 'prob_under_goals_1.5',\n", + " 'prob_under_goals_2.5',\n", + " 'prob_under_goals_3.5',\n", + " 'prob_under_goals_4.5',\n", + " 'ratio_over_corners_11.5_a',\n", + " 'ratio_over_corners_11.5_diff',\n", + " 'ratio_over_corners_11.5_h',\n", + " 'ratio_over_corners_9.5_a',\n", + " 'ratio_over_corners_9.5_diff',\n", + " 'ratio_over_corners_9.5_h',\n", + " 'ratio_under_corners_10.5_a',\n", + " 'ratio_under_corners_10.5_diff',\n", + " 'ratio_under_corners_10.5_h',\n", + " 'ratio_under_goals_4.5_a',\n", + " 'ratio_under_goals_4.5_diff',\n", + " 'ratio_under_goals_4.5_h',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_over_goals_3.5',\n", + " 'raw_prob_over_goals_3.5',\n", + " 'raw_prob_over_goals_4.5',\n", + " 'raw_prob_over_goals_4.5',\n", + " 'raw_prob_under_goals_1.5',\n", + " 'raw_prob_under_goals_2.5',\n", + " 'raw_prob_under_goals_3.5',\n", + " 'raw_prob_under_goals_4.5',\n", + " 'red_card_1t_std_a',\n", + " 'red_card_1t_std_diff',\n", + " 'red_card_1t_std_h',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_2t_mean_diff',\n", + " 'red_card_2t_mean_h',\n", + " 'red_card_mean_a',\n", + " 'red_card_mean_diff',\n", + " 'red_card_mean_h',\n", + " 'red_card_std_a',\n", + " 'red_card_std_diff',\n", + " 'red_card_std_h',\n", + " 'rescinded_red_card_mean_a',\n", + " 'rescinded_red_card_mean_diff',\n", + " 'rescinded_red_card_mean_h',\n", + " 'rescinded_red_card_std_a',\n", + " 'rescinded_red_card_std_diff',\n", + " 'rescinded_red_card_std_h',\n", + " 'right_to_left_goals_mean_a',\n", + " 'right_to_left_goals_mean_a',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_mean_h',\n", + " 'right_to_left_goals_mean_h',\n", + " 'right_to_left_goals_std_a',\n", + " 'right_to_left_goals_std_diff',\n", + " 'right_to_left_goals_std_h',\n", + " 'rightside_pass_div_accurate_pass_std_a',\n", + " 'rightside_pass_div_accurate_pass_std_diff',\n", + " 'rightside_pass_div_accurate_pass_std_h',\n", + " 'rightside_pass_div_leftside_pass_mean_a',\n", + " 'rightside_pass_div_leftside_pass_mean_diff',\n", + " 'rightside_pass_div_leftside_pass_mean_h',\n", + " 'saves_std_a',\n", + " 'saves_std_diff',\n", + " 'saves_std_h',\n", + " 'second_yellow_mean_a',\n", + " 'second_yellow_mean_diff',\n", + " 'second_yellow_mean_h',\n", + " 'second_yellow_std_a',\n", + " 'second_yellow_std_diff',\n", + " 'second_yellow_std_h',\n", + " 'shots_div_passes_left_mean_a',\n", + " 'shots_div_passes_left_mean_diff',\n", + " 'shots_div_passes_left_mean_h',\n", + " 'shots_div_passes_right_mean_a',\n", + " 'shots_div_passes_right_mean_diff',\n", + " 'shots_div_passes_right_mean_h',\n", + " 'shots_div_passes_right_std_a',\n", + " 'shots_div_passes_right_std_diff',\n", + " 'shots_div_passes_right_std_h',\n", + " 'shots_mul_goals_mean_a',\n", + " 'shots_mul_goals_mean_diff',\n", + " 'shots_mul_goals_mean_h',\n", + " 'shots_std_a',\n", + " 'shots_std_diff',\n", + " 'shots_std_h',\n", + " 'successful_final_third_passes_std_a',\n", + " 'successful_final_third_passes_std_diff',\n", + " 'successful_final_third_passes_std_h',\n", + " 'total_bets_under_cards_4.5_a',\n", + " 'total_bets_under_cards_4.5_diff',\n", + " 'total_bets_under_cards_4.5_h',\n", + " 'total_bets_under_corners_9.5_a',\n", + " 'total_bets_under_corners_9.5_diff',\n", + " 'total_bets_under_corners_9.5_h',\n", + " 'total_clearance_mean_a',\n", + " 'total_clearance_mean_diff',\n", + " 'total_clearance_mean_h',\n", + " 'total_expulsions_ref',\n", + " 'total_fastbreak_std_a',\n", + " 'total_fastbreak_std_diff',\n", + " 'total_fastbreak_std_h',\n", + " 'total_fwd_zone_pass_div_long_pass_own_to_opp_success_std_a',\n", + " 'total_fwd_zone_pass_div_long_pass_own_to_opp_success_std_diff',\n", + " 'total_fwd_zone_pass_div_long_pass_own_to_opp_success_std_h',\n", + " 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_diff',\n", + " 'total_fwd_zone_pass_std_a',\n", + " 'total_fwd_zone_pass_std_diff',\n", + " 'total_fwd_zone_pass_std_h',\n", + " 'total_high_claim_mean_a',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_high_claim_mean_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_diff',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_keeper_sweeper_std_a',\n", + " 'total_keeper_sweeper_std_diff',\n", + " 'total_keeper_sweeper_std_h',\n", + " 'total_launches_mean_a',\n", + " 'total_launches_mean_diff',\n", + " 'total_launches_mean_h',\n", + " 'total_launches_std_a',\n", + " 'total_launches_std_diff',\n", + " 'total_launches_std_h',\n", + " 'total_layoffs_mean_a',\n", + " 'total_layoffs_mean_diff',\n", + " 'total_layoffs_mean_h',\n", + " 'total_layoffs_std_a',\n", + " 'total_layoffs_std_diff',\n", + " 'total_layoffs_std_h',\n", + " 'total_red_card_match_ref',\n", + " 'total_red_card_mean_a',\n", + " 'total_red_card_mean_diff',\n", + " 'total_red_card_mean_h',\n", + " 'total_red_card_std_a',\n", + " 'total_red_card_std_diff',\n", + " 'total_red_card_std_h',\n", + " 'total_second_yel_card_away_ref',\n", + " 'total_second_yel_card_home_ref',\n", + " 'total_second_yel_card_ref',\n", + " 'total_through_ball_mean_a',\n", + " 'total_through_ball_mean_diff',\n", + " 'total_through_ball_mean_h',\n", + " 'total_through_ball_std_a',\n", + " 'total_through_ball_std_diff',\n", + " 'total_through_ball_std_h',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_throws_std_h',\n", + " 'total_win_pct_over_corners_9.5_a',\n", + " 'total_win_pct_over_corners_9.5_diff',\n", + " 'total_win_pct_over_corners_9.5_h',\n", + " 'total_win_pct_over_goals_2.5_a',\n", + " 'total_win_pct_over_goals_2.5_diff',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_1.5_diff',\n", + " 'total_win_pct_under_goals_1.5_h',\n", + " 'total_win_pct_under_goals_3.5_a',\n", + " 'total_win_pct_under_goals_3.5_diff',\n", + " 'total_win_pct_under_goals_3.5_h',\n", + " 'total_yel_card_std_a',\n", + " 'total_yel_card_std_diff',\n", + " 'total_yel_card_std_h',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_over_goals_2.5_h',\n", + " 'win_pct_home_over_cards_6.5_a',\n", + " 'win_pct_home_over_cards_6.5_diff',\n", + " 'win_pct_home_over_cards_6.5_h',\n", + " 'win_pct_home_over_goals_2.5_a',\n", + " 'win_pct_home_over_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_cards_4.5_a',\n", + " 'win_pct_home_under_cards_4.5_diff',\n", + " 'win_pct_home_under_cards_4.5_h',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_a',\n", + " 'won_corners_ratio_mean_diff',\n", + " 'won_corners_ratio_mean_diff',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_mean_h',\n", + " 'won_corners_ratio_std_a',\n", + " 'won_corners_ratio_std_diff',\n", + " 'won_corners_ratio_std_h'])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "common_feat = list(set([\"_\".join(x.split(\"_\")[:-1]) for x in selected_features]))\n", + "new_subset = [x for x in train_data.columns for c in common_feat if c in x]\n", + "\n", + "len(selected_features), len(new_subset), sorted(new_subset)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"Monkey patch feature_selection module.\"\"\"\n", + "from typing import List, Tuple\n", + "\n", + "# from feature_selection import FeatureSelection\n", + "\n", + "\n", + "def get_root_features(feature_list: List) -> Tuple[List, List]:\n", + " \"\"\"Get the features related to teams, i.e., those ended with \"_a\", \"_h\", \"_diff\".\"\"\"\n", + " # Conditions\n", + " cond1 = lambda x: x.endswith(\"_h\")\n", + " cond2 = lambda x: x.endswith(\"_a\")\n", + " cond3 = lambda x: x.endswith(\"_diff\")\n", + " # Features ended with _h, _a, _diff\n", + " sublist = [c for c in feature_list if (cond1(c) or cond2(c) or cond3(c))]\n", + " return sublist, list(set([\"_\".join(c.split(\"_\")[:-1]) for c in sublist]))\n", + "\n", + "\n", + "def append_list(root_features: List, og_columns: List):\n", + " \"\"\"Append suffixes to the incoming feature labels.\"\"\"\n", + " # Create empty list\n", + " dressed_list = list()\n", + " # Add suffixes to each root label\n", + " # dressed_list = [c for root in root_features for c in df_columns if c.startswith(root)]\n", + " for c in root_features:\n", + " dressed_list.append(f\"{c}_h\")\n", + " dressed_list.append(f\"{c}_a\")\n", + " dressed_list.append(f\"{c}_diff\")\n", + " dressed_list = [c for c in dressed_list if c in og_columns]\n", + " # return list(set(dressed_list))\n", + " return dressed_list\n", + "\n", + "\n", + "def massage_feat_list(feature_list: List, og_columns: List):\n", + " \"\"\"\n", + " Add team features to the incoming list.\n", + "\n", + " Given a feature list, this function adds the full trio of team\n", + " features (*_h, *_a, *_diff) to those already present that are\n", + " related to team statistics.\n", + " \"\"\"\n", + " feature_list = feature_list.copy()\n", + " # Get list of match features and root\n", + " sublist, root = get_root_features(feature_list)\n", + " # Get features not related to teams\n", + " no_team = list(set(feature_list) - set(sublist))\n", + " # Add suffixes to roots\n", + " dressed = append_list(root_features=root, og_columns=og_columns.copy())\n", + " # return list(set(no_team + dressed))\n", + " return no_team + dressed\n", + "\n", + "\n", + "def finalize_list(feature_list: List, df_columns: List):\n", + " \"\"\"\n", + " Complete the feature_list returned by the selection module.\n", + "\n", + " Once the number of features has been reduced to a subset of\n", + " relevant features, this function completes the list by adding\n", + " team features to those already present.\n", + "\n", + " If a team feature is present, but the set only contains the one\n", + " related to the home or away team, the function adds the corresponding\n", + " feature related to the difference between teams, i.e., team_feat_diff.\n", + " \"\"\"\n", + " feature_list = feature_list.copy()\n", + " # Elements with _h, _a, _diff\n", + " sublist, roots = get_root_features(feature_list)\n", + " # List to be used as building block\n", + " final_list = list(set(feature_list) - set(sublist))\n", + " # Check for team features\n", + " for root in roots:\n", + " triplet = [f\"{root}_h\", f\"{root}_a\", f\"{root}_diff\"]\n", + " subset = [c for tri in triplet for c in sublist if c == tri]\n", + " if len(subset) < 2 and not subset[0].endswith(\"_diff\"):\n", + " subset.append(f\"{root}_diff\")\n", + " final_list = final_list + subset\n", + " final_list = [c for c in final_list if c in df_columns]\n", + " return final_list\n", + "\n", + "\n", + "def patch_repeat_pipeline(self):\n", + " \"\"\"Iterate over the process to create the feature list and repeat it self.repeat times (PATCH).\"\"\"\n", + " i = 0\n", + " while len(self.feature_list) > self.target_features:\n", + " i += 1\n", + " print(f\"{i} iteration\")\n", + " # Call iteration\n", + " self.create_feature_list()\n", + " self.feature_list = massage_feat_list(\n", + " feature_list=self.feature_list, og_columns=self.x_df.columns\n", + " )\n", + " if len(self.feature_list) <= 1:\n", + " break\n", + " return finalize_list(feature_list=self.feature_list, df_columns=self.x_df.columns)\n", + "\n", + "def patch_train_model(self):\n", + " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", + " # Selected dataset\n", + " selected_cols = self.feature_list + [self.target]\n", + " train_data = self.dataset[selected_cols] if self.x_df.empty else self.x_df[selected_cols]\n", + " # Numeric features\n", + " self.setup_kwargs[\"numeric_features\"] = [\n", + " c for c in self.numeric_features if c in self.feature_list\n", + " ]\n", + " # Ignore features\n", + " self.setup_kwargs[\"ignore_features\"] = [\n", + " c for c in self.ignore_features if c in self.feature_list\n", + " ]\n", + " self.setup_kwargs[\"feature_interaction\"]: False\n", + " # Initialize pycaret setup\n", + " setup(data=train_data, target=self.target, **self.setup_kwargs)\n", + " # Get train dataset and preprocessed dataframe\n", + " self.x_train = get_config(\"X_train\")\n", + " if self.x_df.empty: # TODO change x_df by dataset and add flag?\n", + " self.x_df = pd.concat([get_config(\"X\"), get_config(\"y\")], axis=1)\n", + " self.setup_kwargs[\"preprocess\"] = False # Turn off preprocessing\n", + " # Compare models\n", + " self.top_models = self._training_function(**self._args)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def patch_train_model(self):\n", + " \"\"\"Preprocess the data and select self.number_models top models.\"\"\"\n", + " # Selected dataset\n", + " selected_cols = self.feature_list + [self.target]\n", + " train_data = self.dataset[selected_cols] if self.x_df.empty else self.x_df[selected_cols]\n", + " # Numeric features\n", + " self.setup_kwargs[\"numeric_features\"] = [\n", + " c for c in self.numeric_features if c in self.feature_list\n", + " ]\n", + " # Ignore features\n", + " self.setup_kwargs[\"ignore_features\"] = [\n", + " c for c in self.ignore_features if c in self.feature_list\n", + " ]\n", + " self.setup_kwargs[\"feature_interaction\"]: False\n", + " # Initialize pycaret setup\n", + " setup(data=train_data, target=self.target, **self.setup_kwargs)\n", + " # Get train dataset and preprocessed dataframe\n", + " self.x_train = get_config(\"X_train\")\n", + " if self.x_df.empty: # TODO change x_df by dataset and add flag?\n", + " self.x_df = pd.concat([get_config(\"X\"), get_config(\"y\")], axis=1)\n", + " self.setup_kwargs[\"preprocess\"] = False # Turn off preprocessing\n", + " # Compare models\n", + " self.top_models = self._training_function(**self._args)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:param: Setting non-Parameter class attribute FeatureSelection.train_model = \n" + ] + } + ], + "source": [ + "FeatureSelection.train_model = patch_train_model" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:param: Setting non-Parameter class attribute FeatureSelection.repeat_pipeline = \n" + ] + } + ], + "source": [ + "FeatureSelection.repeat_pipeline = patch_repeat_pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "FeatureSelection.repeat_pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "FeatureSelection.filter_tuned_duplicate??" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 iteration\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.51860.52990.50000.52860.51390.03780.0378
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC
0Logistic Regression0.50890.53220.48920.51860.50350.01860.0186
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "metric_param = {\n", + " \"Accuracy\": 0.1,\n", + " \"AUC\": 0.1,\n", + " \"Recall\": 0.1,\n", + " \"Precision\": 0.1,\n", + " \"F1\": 0.1,\n", + " \"Kappa\": -1.0,\n", + " \"MCC\": -1.0,\n", + " }\n", + "feat_sel = FeatureSelection(target=target,\n", + " dataset=train_data.dropna(),#[list(set(new_subset+new_feat+[target]))],\n", + " target_features=0.56,\n", + " filter_metrics=metric_param,\n", + " include=[\"lr\"],\n", + " setup_kwargs=setup_kwargs,\n", + " optimize=True,\n", + " opt_list=[\"AUC\" , \"Accuracy\" , \"Precision\" , \"Recall\"],\n", + " number_features = 0.56\n", + " )\n", + "triplet_selected_features = feat_sel.repeat_pipeline()\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1445" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(triplet_selected_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
win_pct_hdraw_pct_hloss_pct_hwin_streak_hloss_streak_hdraw_streak_hpoints_hranking_hATT_hMED_h...total_expulsions_reftotal_tackle_reftotal_fk_foul_reftotal_penalty_match_reftotal_hand_ball_reftotal_fouls_home_reftotal_fouls_away_reftotal_fouls_match_reffk_per_tackle_refgoals_2.5
match_id
1069833_german_bundesliga-1.6439011.5332770.214646-0.714075-0.7834401.6126660.639803-0.1798710.315282-0.131555...0.9853181.101278-1.029729-0.7938010.917055-0.732395-0.728244-0.827393-1.2180831
1069835_german_bundesliga-0.664834-1.4299441.6608611.123439-0.783440-0.5993290.3722920.631282-0.405111-0.514660...-0.3691700.356790-0.346304-1.4545420.1564030.124371-0.627903-0.305101-0.3806860
1069836_german_bundesliga-0.664834-0.1996620.974545-0.7140751.710316-0.5993290.3722920.959403-1.008551-0.857581...0.5429200.7745971.110759-1.454542-0.9075351.3744380.1975980.8643200.3378280
1069834_german_bundesliga-0.6648342.212205-1.666619-0.714075-0.7834401.8697950.058238-0.025558-0.717569-1.320451...1.4062180.3919961.5652952.2651591.3012841.1684611.6353051.6404320.7644581
1069842_german_bundesliga-0.6648340.7593400.214646-0.714075-0.7834401.6126660.7212680.389111-0.717569-0.514660...-0.2965110.965913-0.156935-0.105425-0.5903730.562788-0.929066-0.234115-0.3699540
..................................................................
2219403_spanish_la_liga-1.6439010.7593400.974545-0.7140751.710316-0.599329-0.2450430.959403-0.2385780.080462...0.3721710.7217250.1213701.021130-0.051437-0.0582920.2724040.093577-0.3718110
2229046_italian_serie_a0.203837-1.4299440.974545-0.7140750.985387-0.599329-0.1193510.744759-0.4051110.306435...1.682687-2.4894700.4173300.7639420.5680770.5834740.2724040.4607101.8576691
2210408_english_premier_league-1.6439011.5332770.214646-0.7140750.985387-0.599329-1.1941450.3891110.315282-0.131555...0.3721711.580043-0.084230-0.1054250.6859310.208313-0.1270360.017975-1.0406550
2229048_italian_serie_a0.2038370.759340-0.670644-0.7140750.985387-0.599329-0.2450431.160365-0.405111-0.514660...-1.6396141.9748270.809434-2.368850-0.5903730.2758420.8696800.638675-0.8024200
2210403_english_premier_league-0.6648341.533277-0.670644-0.714075-0.7834401.612666-0.7286072.1035500.121476-0.329155...-0.0223970.586037-1.3955551.504698-1.906150-1.713468-1.029543-1.521511-1.5830140
\n", + "

2907 rows × 2200 columns

\n", + "
" + ], + "text/plain": [ + " win_pct_h draw_pct_h loss_pct_h \\\n", + "match_id \n", + "1069833_german_bundesliga -1.643901 1.533277 0.214646 \n", + "1069835_german_bundesliga -0.664834 -1.429944 1.660861 \n", + "1069836_german_bundesliga -0.664834 -0.199662 0.974545 \n", + "1069834_german_bundesliga -0.664834 2.212205 -1.666619 \n", + "1069842_german_bundesliga -0.664834 0.759340 0.214646 \n", + "... ... ... ... \n", + "2219403_spanish_la_liga -1.643901 0.759340 0.974545 \n", + "2229046_italian_serie_a 0.203837 -1.429944 0.974545 \n", + "2210408_english_premier_league -1.643901 1.533277 0.214646 \n", + "2229048_italian_serie_a 0.203837 0.759340 -0.670644 \n", + "2210403_english_premier_league -0.664834 1.533277 -0.670644 \n", + "\n", + " win_streak_h loss_streak_h draw_streak_h \\\n", + "match_id \n", + "1069833_german_bundesliga -0.714075 -0.783440 1.612666 \n", + "1069835_german_bundesliga 1.123439 -0.783440 -0.599329 \n", + "1069836_german_bundesliga -0.714075 1.710316 -0.599329 \n", + "1069834_german_bundesliga -0.714075 -0.783440 1.869795 \n", + "1069842_german_bundesliga -0.714075 -0.783440 1.612666 \n", + "... ... ... ... \n", + "2219403_spanish_la_liga -0.714075 1.710316 -0.599329 \n", + "2229046_italian_serie_a -0.714075 0.985387 -0.599329 \n", + "2210408_english_premier_league -0.714075 0.985387 -0.599329 \n", + "2229048_italian_serie_a -0.714075 0.985387 -0.599329 \n", + "2210403_english_premier_league -0.714075 -0.783440 1.612666 \n", + "\n", + " points_h ranking_h ATT_h MED_h ... \\\n", + "match_id ... \n", + "1069833_german_bundesliga 0.639803 -0.179871 0.315282 -0.131555 ... \n", + "1069835_german_bundesliga 0.372292 0.631282 -0.405111 -0.514660 ... \n", + "1069836_german_bundesliga 0.372292 0.959403 -1.008551 -0.857581 ... \n", + "1069834_german_bundesliga 0.058238 -0.025558 -0.717569 -1.320451 ... \n", + "1069842_german_bundesliga 0.721268 0.389111 -0.717569 -0.514660 ... \n", + "... ... ... ... ... ... \n", + "2219403_spanish_la_liga -0.245043 0.959403 -0.238578 0.080462 ... \n", + "2229046_italian_serie_a -0.119351 0.744759 -0.405111 0.306435 ... \n", + "2210408_english_premier_league -1.194145 0.389111 0.315282 -0.131555 ... \n", + "2229048_italian_serie_a -0.245043 1.160365 -0.405111 -0.514660 ... \n", + "2210403_english_premier_league -0.728607 2.103550 0.121476 -0.329155 ... \n", + "\n", + " total_expulsions_ref total_tackle_ref \\\n", + "match_id \n", + "1069833_german_bundesliga 0.985318 1.101278 \n", + "1069835_german_bundesliga -0.369170 0.356790 \n", + "1069836_german_bundesliga 0.542920 0.774597 \n", + "1069834_german_bundesliga 1.406218 0.391996 \n", + "1069842_german_bundesliga -0.296511 0.965913 \n", + "... ... ... \n", + "2219403_spanish_la_liga 0.372171 0.721725 \n", + "2229046_italian_serie_a 1.682687 -2.489470 \n", + "2210408_english_premier_league 0.372171 1.580043 \n", + "2229048_italian_serie_a -1.639614 1.974827 \n", + "2210403_english_premier_league -0.022397 0.586037 \n", + "\n", + " total_fk_foul_ref total_penalty_match_ref \\\n", + "match_id \n", + "1069833_german_bundesliga -1.029729 -0.793801 \n", + "1069835_german_bundesliga -0.346304 -1.454542 \n", + "1069836_german_bundesliga 1.110759 -1.454542 \n", + "1069834_german_bundesliga 1.565295 2.265159 \n", + "1069842_german_bundesliga -0.156935 -0.105425 \n", + "... ... ... \n", + "2219403_spanish_la_liga 0.121370 1.021130 \n", + "2229046_italian_serie_a 0.417330 0.763942 \n", + "2210408_english_premier_league -0.084230 -0.105425 \n", + "2229048_italian_serie_a 0.809434 -2.368850 \n", + "2210403_english_premier_league -1.395555 1.504698 \n", + "\n", + " total_hand_ball_ref total_fouls_home_ref \\\n", + "match_id \n", + "1069833_german_bundesliga 0.917055 -0.732395 \n", + "1069835_german_bundesliga 0.156403 0.124371 \n", + "1069836_german_bundesliga -0.907535 1.374438 \n", + "1069834_german_bundesliga 1.301284 1.168461 \n", + "1069842_german_bundesliga -0.590373 0.562788 \n", + "... ... ... \n", + "2219403_spanish_la_liga -0.051437 -0.058292 \n", + "2229046_italian_serie_a 0.568077 0.583474 \n", + "2210408_english_premier_league 0.685931 0.208313 \n", + "2229048_italian_serie_a -0.590373 0.275842 \n", + "2210403_english_premier_league -1.906150 -1.713468 \n", + "\n", + " total_fouls_away_ref total_fouls_match_ref \\\n", + "match_id \n", + "1069833_german_bundesliga -0.728244 -0.827393 \n", + "1069835_german_bundesliga -0.627903 -0.305101 \n", + "1069836_german_bundesliga 0.197598 0.864320 \n", + "1069834_german_bundesliga 1.635305 1.640432 \n", + "1069842_german_bundesliga -0.929066 -0.234115 \n", + "... ... ... \n", + "2219403_spanish_la_liga 0.272404 0.093577 \n", + "2229046_italian_serie_a 0.272404 0.460710 \n", + "2210408_english_premier_league -0.127036 0.017975 \n", + "2229048_italian_serie_a 0.869680 0.638675 \n", + "2210403_english_premier_league -1.029543 -1.521511 \n", + "\n", + " fk_per_tackle_ref goals_2.5 \n", + "match_id \n", + "1069833_german_bundesliga -1.218083 1 \n", + "1069835_german_bundesliga -0.380686 0 \n", + "1069836_german_bundesliga 0.337828 0 \n", + "1069834_german_bundesliga 0.764458 1 \n", + "1069842_german_bundesliga -0.369954 0 \n", + "... ... ... \n", + "2219403_spanish_la_liga -0.371811 0 \n", + "2229046_italian_serie_a 1.857669 1 \n", + "2210408_english_premier_league -1.040655 0 \n", + "2229048_italian_serie_a -0.802420 0 \n", + "2210403_english_premier_league -1.583014 0 \n", + "\n", + "[2907 rows x 2200 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feat_sel.x_df" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "feat_sel.dataset.to_csv('Vicente_Dataset.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "feat_sel.x_df.to_csv('Vicente_x_df.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4c7541287bfa4753b41e5968084b85b4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(feat_sel.top_models[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "error = ['win_pct_home_over_corners_11.5_h', 'ranking_a', 'odds_home_over_corners_6.5_diff', 'total_bets_under_corners_6.5_h', 'win_pct_away_over_cards_6.5_diff', 'ratio_under_cards_2.5_a', 'total_clearance_mean_a', 'red_card_1t_mean_h', 'total_bets_over_cards_5.5_a', 'head_clearance_std_diff', 'att_obx_left_mean_a', 'MED_mean_h', 'pts_dropped_winning_pos_mean_h', 'win_pct_home_under_corners_11.5_diff', 'fifty_fifty_std_h', 'total_bets_under_cards_4.5_a', 'red_card_2t_std_h', 'total_bets_over_cards_4.5_h', 'ranking_mean_h', 'penalty_save_std_h', 'red_card_std_h', 'att_cmiss_high_left_mean_h', 'att_cmiss_high_left_mean_a', 'att_post_right_mean_a', 'total_bets_over_corners_9.5_h', 'win_pct_home_under_corners_11.5_a', 'head_clearance_mean_h', 'effective_head_clearance_mean_a', 'odds_home_under_goals_0.5_a', 'ATT_h_mul_shots_mul_goals_mean_a', 'total_bets_under_cards_4.5_diff', 'red_card_2t_std_a', 'accurate_keeper_throws_mean_a', 'ratio_over_cards_2.5_a', 'ranking_diff', 'att_lg_centre_std_h', 'corners_std_diff', 'effective_clearance_mean_h', 'att_obx_left_std_h', 'att_freekick_goal_std_h', 'ratio_over_cards_2.5_h', 'odds_away_over_corners_9.5_a', 'att_goal_high_centre_std_h', 'total_red_card_std_a', 'clearance_off_line_mean_h', 'head_clearance_mean_diff', 'odds_away_over_both_score_a', 'own_goals_mean_h', 'ratio_over_cards_6.5_h', 'att_obxd_right_std_h', 'att_lg_centre_mean_a', 'pts_dropped_winning_pos_mean_diff', 'att_freekick_goal_std_a', 'fifty_fifty_std_a', 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_a', 'ATT_h_mul_shots_mul_goals_mean_h', 'total_bets_over_corners_9.5_diff', 'shots_mul_goals_mean_diff', 'DEF_mean_diff', 'win_pct_home_over_cards_6.5_diff', 'total_bets_over_cards_2.5_h', 'total_bets_under_cards_2.5_a', 'own_goals_std_a', 'ratio_under_corners_6.5_a', 'last_man_tackle_std_h', 'att_goal_high_centre_std_a', 'att_ibox_own_goal_mean_a', 'ratio_under_cards_2.5_h', 'att_ibox_own_goal_std_h', 'penalty_save_mean_a', 'att_post_right_std_h', 'att_hd_post_std_a', 'att_obxd_right_mean_a', 'ratio_under_corners_6.5_h', 'total_bets_under_goals_2.5_diff', 'ratio_over_cards_6.5_a', 'last_man_tackle_mean_a', 'att_obx_right_mean_h', 'total_bets_under_cards_2.5_diff', 'att_pen_target_mean_a', 'total_bets_under_corners_6.5_a', 'total_clearance_mean_diff', 'att_cmiss_high_right_std_a', 'total_bets_under_corners_9.5_a', 'goal_fastbreak_mean_a', 'odds_home_under_goals_0.5_h', 'att_obx_right_mean_a', 'att_cmiss_high_right_mean_h', 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_h'] " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['att_lg_centre_std_h']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[c for c in feat_sel.dataset.columns if 'att_lg_centre_std_h' in c]" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['ATT_h_mul_shots_mul_goals_mean_a',\n", + " 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_a',\n", + " 'ATT_h_mul_shots_mul_goals_mean_h',\n", + " 'total_fwd_zone_pass_mean_diff_mul_goal_kicks_per_shot_mean_h'],\n", + " dtype=' 10,\n", + " feats.matches[\"competition\"].isin({\"mexican_primera\", 'us_major_league_soccer'}))\n", + "index = feats.matches[~ix].index" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "test_feats = ['acc_cross_nocorner_pct_std_a',\n", + " 'acc_cross_nocorner_pct_std_diff',\n", + " 'acc_cross_nocorner_pct_std_h',\n", + " 'accurate_flick_on_mean_h',\n", + " 'accurate_flick_on_mean_a',\n", + " 'accurate_freekick_cross_mean_a',\n", + " 'accurate_freekick_cross_mean_diff',\n", + " 'accurate_freekick_cross_mean_h',\n", + " 'accurate_goal_kicks_mean_diff',\n", + " 'accurate_goal_kicks_std_a',\n", + " 'accurate_goal_kicks_std_diff',\n", + " 'accurate_goal_kicks_std_h',\n", + " 'accurate_keeper_sweeper_mean_a',\n", + " 'accurate_keeper_sweeper_std_diff',\n", + " 'accurate_keeper_sweeper_std_h',\n", + " 'accurate_pass_std_a',\n", + " 'accurate_pass_std_h',\n", + " 'accurate_through_ball_mean_diff',\n", + " 'att_assist_openplay_std_a',\n", + " 'att_assist_openplay_std_h',\n", + " 'att_cmiss_left_mean_a',\n", + " 'att_cmiss_left_mean_h',\n", + " 'att_cmiss_left_std_a',\n", + " 'att_cmiss_left_std_diff',\n", + " 'att_cmiss_left_std_h',\n", + " 'att_goal_high_centre_mean_diff',\n", + " 'att_goal_high_centre_std_diff',\n", + " 'att_goal_high_right_std_a',\n", + " 'att_goal_low_centre_mean_diff',\n", + " 'att_goal_low_centre_mean_h',\n", + " 'att_goal_low_centre_std_a',\n", + " 'att_goal_low_centre_std_h',\n", + " 'att_hd_goal_mean_a',\n", + " 'att_hd_goal_mean_h',\n", + " 'att_hd_target_mean_a',\n", + " 'att_hd_target_mean_h',\n", + " 'att_ibox_own_goal_mean_diff',\n", + " 'att_ibox_own_goal_std_h',\n", + " 'att_ibox_own_goal_std_a',\n", + " 'att_miss_high_mean_a',\n", + " 'att_miss_high_mean_h',\n", + " 'att_miss_high_right_mean_diff',\n", + " 'att_obxd_right_mean_diff',\n", + " 'att_obxd_right_std_diff',\n", + " 'att_one_on_one_mean_h',\n", + " 'att_one_on_one_mean_a',\n", + " 'att_one_on_one_std_diff',\n", + " 'att_one_on_one_std_h',\n", + " 'att_post_high_std_a',\n", + " 'att_post_high_std_h',\n", + " 'att_post_right_mean_a',\n", + " 'att_post_right_mean_h',\n", + " 'attempts_ibox_std_a',\n", + " 'attempts_ibox_std_h',\n", + " 'backward_pass_mean_diff',\n", + " 'backward_pass_mean_h',\n", + " 'big_chance_created_mean_h',\n", + " 'big_chance_created_std_diff',\n", + " 'clean_sheet_std_diff',\n", + " 'contentious_decision_mean_a',\n", + " 'contentious_decision_mean_diff',\n", + " 'contentious_decision_std_a',\n", + " 'contentious_decision_std_h',\n", + " 'duel_won_pct_mean_diff',\n", + " 'effective_clearance_mean_diff',\n", + " 'error_lead_to_goal_mean_diff',\n", + " 'error_lead_to_goal_std_diff',\n", + " 'first_yellow_card_1t_mean_h',\n", + " 'first_yellow_card_1t_mean_a',\n", + " 'foul_throw_in_std_diff',\n", + " 'fouled_final_third_mean_diff',\n", + " 'goal_assist_deadball_mean_diff',\n", + " 'goal_assist_openplay_std_diff',\n", + " 'goal_assist_openplay_std_h',\n", + " 'goal_assist_setplay_std_a',\n", + " 'goal_assist_setplay_std_diff',\n", + " 'goal_assist_setplay_std_h',\n", + " 'goal_assist_std_diff',\n", + " 'goals_mean_diff',\n", + " 'goals_openplay_std_h',\n", + " 'goals_openplay_std_a',\n", + " 'good_high_claim_mean_diff',\n", + " 'high_to_low_goals_mean_a',\n", + " 'high_to_low_goals_mean_diff',\n", + " 'high_to_low_goals_std_a',\n", + " 'high_to_low_goals_std_h',\n", + " 'imp_prob_under_goals_0.5_h',\n", + " 'imp_prob_under_goals_2.5_diff',\n", + " 'interception_mean_a',\n", + " 'interception_mean_diff',\n", + " 'interception_mean_h',\n", + " 'interceptions_in_box_std_a',\n", + " 'interceptions_in_box_std_diff',\n", + " 'interceptions_in_box_std_h',\n", + " 'last_man_tackle_mean_a',\n", + " 'last_man_tackle_mean_diff',\n", + " 'left_div_right_foot_goals_std_diff',\n", + " 'leftside_pass_mean_a',\n", + " 'leftside_pass_mean_h',\n", + " 'leftside_pass_std_a',\n", + " 'long_pass_own_to_opp_mean_diff',\n", + " 'long_pass_own_to_opp_mean_h',\n", + " 'no_foot_goals_ratio_std_a',\n", + " 'no_foot_goals_ratio_std_diff',\n", + " 'no_foot_goals_ratio_std_h',\n", + " 'odd_ratio_under_corners_10.5',\n", + " 'odd_ratio_under_corners_8.5',\n", + " 'odds_home_under_both_score_h',\n", + " 'odds_away_under_both_score_a',\n", + " 'odds_away_under_goals_4.5_a',\n", + " 'odds_home_under_goals_4.5_h',\n", + " 'odds_away_over_goals_4.5_a',\n", + " 'odds_home_over_goals_4.5_h',\n", + " 'odds_home_under_goals_0.5_diff',\n", + " 'odds_home_under_goals_0.5_h',\n", + " 'own_goals_std_h',\n", + " 'own_goals_std_a',\n", + " 'pen_goals_conceded_mean_diff',\n", + " 'penalty_faced_std_a',\n", + " 'penalty_won_std_a',\n", + " 'penalty_faced_std_h',\n", + " 'penalty_won_std_h',\n", + " 'poss_won_att_3rd_std_a',\n", + " 'poss_won_att_3rd_std_diff',\n", + " 'poss_won_att_3rd_std_h',\n", + " 'post_scoring_att_std_a',\n", + " 'post_scoring_att_std_h',\n", + " 'prob_squared_under_goals_2.5',\n", + " 'pts_dropped_winning_pos_mean_a',\n", + " 'pts_dropped_winning_pos_std_diff',\n", + " 'pts_dropped_winning_pos_std_h',\n", + " 'ratio_over_goals_2.5_a',\n", + " 'ratio_over_goals_2.5_h',\n", + " 'ratio_under_goals_2.5_a',\n", + " 'ratio_under_goals_2.5_diff',\n", + " 'raw_prob_over_goals_1.5',\n", + " 'raw_prob_over_goals_2.5',\n", + " 'raw_prob_over_goals_3.5',\n", + " 'raw_prob_under_goals_1.5',\n", + " 'raw_prob_under_goals_2.5',\n", + " 'raw_prob_under_goals_3.5',\n", + " 'raw_prob_under_goals_4.5',\n", + " 'red_card_1t_mean_a',\n", + " 'red_card_1t_mean_diff',\n", + " 'red_card_1t_mean_h',\n", + " 'red_card_2t_mean_a',\n", + " 'red_card_2t_mean_diff',\n", + " 'red_card_mean_h',\n", + " 'red_card_mean_a',\n", + " 'red_card_std_diff',\n", + " 'right_to_left_goals_mean_diff',\n", + " 'right_to_left_goals_std_diff',\n", + " 'rightside_pass_div_leftside_pass_mean_a',\n", + " 'rightside_pass_div_leftside_pass_mean_h',\n", + " 'second_yellow_mean_h',\n", + " 'shots_mul_goals_std_h',\n", + " 'second_yellow_mean_a',\n", + " 'shots_mul_goals_std_a',\n", + " 'successful_final_third_passes_mean_a',\n", + " 'successful_final_third_passes_mean_diff',\n", + " 'successful_final_third_passes_std_a',\n", + " 'successful_final_third_passes_std_diff',\n", + " 'successful_put_through_std_a',\n", + " 'successful_put_through_std_diff',\n", + " 'successful_put_through_std_h',\n", + " 'total_clearance_mean_a',\n", + " 'total_clearance_mean_h',\n", + " 'total_fastbreak_std_diff',\n", + " 'total_high_claim_mean_a',\n", + " 'total_high_claim_mean_diff',\n", + " 'total_high_claim_mean_h',\n", + " 'total_keeper_sweeper_mean_a',\n", + " 'total_keeper_sweeper_mean_h',\n", + " 'total_launches_std_h',\n", + " 'total_launches_std_a',\n", + " 'total_red_card_mean_h',\n", + " 'total_red_card_mean_a',\n", + " 'total_red_card_std_diff',\n", + " 'total_throws_std_a',\n", + " 'total_throws_std_diff',\n", + " 'total_win_pct_over_goals_1.5_a',\n", + " 'total_win_pct_over_goals_1.5_h',\n", + " 'total_win_pct_over_goals_2.5_a',\n", + " 'total_win_pct_over_goals_2.5_h',\n", + " 'total_win_pct_over_goals_3.5_a',\n", + " 'total_win_pct_over_goals_3.5_h',\n", + " 'total_win_pct_under_goals_1.5_a',\n", + " 'total_win_pct_under_goals_1.5_h',\n", + " 'total_win_pct_under_goals_2.5_a',\n", + " 'total_win_pct_under_goals_2.5_h',\n", + " 'total_win_pct_under_goals_3.5_a',\n", + " 'total_yel_card_std_a',\n", + " 'total_yel_card_std_diff',\n", + " 'total_yel_card_std_h',\n", + " 'win_pct_away_over_goals_2.5_a',\n", + " 'win_pct_away_over_goals_2.5_diff',\n", + " 'win_pct_away_under_goals_2.5_a',\n", + " 'win_pct_away_under_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_a',\n", + " 'win_pct_home_over_goals_2.5_diff',\n", + " 'win_pct_home_over_goals_2.5_h',\n", + " 'win_pct_home_under_goals_2.5_diff',\n", + " 'win_pct_home_under_goals_2.5_h',\n", + " 'winner_mean_diff']" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def setup_dataset(test_date):\n", + " ds = create_dataset(target=target,\n", + " test_date=test_date,\n", + " features=feats,\n", + " odds_features=True,\n", + " include_std=True,\n", + " test_weeks=6,\n", + " ignore_features=IGNORE_FEATURES,\n", + " drop_future_matches=False,\n", + " )\n", + " train_data = ds.train_data.copy()#[ds.train_data.index.map(lambda x: \"us_major_league_soccer\" not in x and \"mexican\" not in x)]\n", + " train_data.drop(columns=[\"hour_rank\", \"hour_before_16\", \"is_weekend\"], inplace=True)\n", + " train_data = train_data[train_data.index.isin(index)][list(set(test_feats)) + [target]].copy()#.reset_index(drop=True)\n", + " test_data = ds.test_set[ds.test_set.index.isin(index)][list(set(test_feats)) + [target]].copy()#.reset_index(drop=True)\n", + " val_data = ds.val_set[ds.val_set.index.isin(index)].copy()\n", + " setup_kwargs = dict(\n", + " preprocess=True,\n", + " test_data=test_data[train_data.columns.tolist()],#.dropna(),\n", + " #numeric_features=[x for x in train_data.columns.tolist() if x != target],\n", + " #custom_pipeline=loaded,\n", + " #train_size=0.75,\n", + " session_id=123,\n", + " normalize=True,\n", + " normalize_method=\"robust\",\n", + " transformation=True,\n", + " ignore_low_variance=True,\n", + " remove_multicollinearity=False,\n", + " multicollinearity_threshold=0.8,\n", + " n_jobs=-1,\n", + " use_gpu=False,\n", + " profile=False,\n", + " #ignore_features=ignore_features,\n", + " fold_strategy=\"stratifiedkfold\",#\"timeseries\",\n", + " remove_perfect_collinearity=True,\n", + " create_clusters=False,\n", + " fold=4,\n", + " feature_selection=False,\n", + " # you can use this to keep the 95 % most relevant features (fat_sel_threshold)\n", + " feature_selection_threshold=0.5,\n", + " combine_rare_levels=False,\n", + " rare_level_threshold=0.02,\n", + " pca=False,\n", + " pca_method=\"linear\",\n", + " pca_components=30,\n", + " polynomial_features=False,\n", + " polynomial_degree=2,\n", + " polynomial_threshold=0.05,\n", + " trigonometry_features=False,\n", + " remove_outliers=True,\n", + " outliers_threshold=0.01,\n", + " feature_ratio=False,\n", + " feature_interaction=False,\n", + " # Makes everything slow AF. use to find out possibly interesting features\n", + " interaction_threshold=0.05,\n", + " fix_imbalance=True,\n", + " log_experiment=False,\n", + " verbose=False,\n", + " silent=True,\n", + " experiment_name=\"lagstest\",\n", + " )\n", + " _ = setup(data=train_data, target=target, **setup_kwargs)\n", + " return train_data, test_data, val_data, ds" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "train_data, test_data, val_data, ds = setup_dataset(\"4-Dec-2021\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "from pycaret.classification import stack_models, ensemble_model, blend_models\n", + "def train_ensemble():\n", + " top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"et\", \"rf\", \"svm\"],\n", + " verbose=True,\n", + " )\n", + " tuned_models = [tune_model(model, optimize=\"MCC\", choose_better=True, n_iter=50, search_library=\"optuna\") for model in top_models]\n", + " cali = [calibrate_model(tuned, method=\"sigmoid\", calibrate_fold=4) for tuned in tuned_models]\n", + " blend = blend_models(cali)\n", + " opti = tune_model(blend, optimize=\"Precision\", choose_better=True, n_iter=50, search_library=\"optuna\")\n", + " return opti, cali, tuned_models" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "from pycaret.classification import stack_models, ensemble_model, blend_models\n", + "def train_linear_models():\n", + " top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"svm\"],\n", + " verbose=True,\n", + " )\n", + " tuned_models = [tune_model(model, optimize=\"MCC\", choose_better=True, n_iter=50, search_library=\"optuna\") for model in top_models]\n", + " cali = [calibrate_model(tuned, method=\"sigmoid\", calibrate_fold=4) for tuned in tuned_models]\n", + " return tuned_models, cali" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Accuracy AUC Recall Prec. F1 Kappa MCC
00.64140.68930.67160.65070.66100.28060.2807
10.59970.65860.63210.61240.62210.19690.1970
20.62160.66790.61230.64420.62780.24350.2439
30.61260.64750.60150.63450.61750.22570.2260
Mean0.61880.66580.62940.63540.63210.23670.2369
SD0.01520.01540.02670.01450.01710.03030.0303
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tuned_linear, cali_linear = train_linear_models()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Model Accuracy AUC Recall Prec. F1 Kappa MCC TT (Sec)
lrLogistic Regression0.61660.67340.58360.65000.60810.23510.24000.3000
ldaLinear Discriminant Analysis0.61660.67050.58920.64750.61150.23470.23870.3025
ridgeRidge Classifier0.61660.00000.58920.64760.61150.23470.23870.2850
svmSVM - Linear Kernel0.58410.00000.54410.61570.57340.17080.17390.3050
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "top_models = compare_models(\n", + " n_select=8,\n", + " sort='MCC',\n", + " include=[\"lr\", \"lda\", \"ridge\", \"svm\"],\n", + " verbose=True,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "SGDClassifier(alpha=0.10126692364605047, average=False, class_weight=None,\n", + " early_stopping=False, epsilon=0.1, eta0=0.001022673152073415,\n", + " fit_intercept=False, l1_ratio=0.2203376725525369,\n", + " learning_rate='optimal', loss='hinge', max_iter=1000,\n", + " n_iter_no_change=5, n_jobs=-1, penalty='l1', power_t=0.5,\n", + " random_state=123, shuffle=True, tol=0.001,\n", + " validation_fraction=0.1, verbose=0, warm_start=False)" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tuned_linear[3]" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6522b430b2a64128ac3789a8d93475f2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(tuned_linear[3])" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a9de03ccce3a4047b615b146297be69e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(ToggleButtons(description='Plot Type:', icons=('',), options=(('Hyperparameters', 'param…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "evaluate_model(cali_linear[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "market=\"goals\"\n", + "cutoff = 2.5\n", + "tips = tips_from_model(model=cali_linear[0],\n", + " test_data=test_data,\n", + " features=feats,\n", + " market=market,\n", + " cutoff=cutoff,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
winprofitexp_payoffexp_payoff_precoddsconfidencecountbuenasmodel
bet_typematch_week
goals_over_2.52021_190.8181820.4345451.193888NaN1.7436360.683591119model
2021_200.7000000.1440001.087417NaN1.6410000.664270107model
2021_210.8000000.3590001.130386NaN1.6850000.671600108model
2021_220.5714290.0400001.130597NaN1.7085710.66280074model
2021_230.500000-0.1400001.216788NaN1.8150000.66775042model
2021_240.6250000.0587501.168317NaN1.7300000.67497585model
2021_250.000000-1.0000001.200240NaN1.8000000.66680010model
goals_under_2.52021_190.7500000.2550001.034973NaN1.6300000.63415043model
2021_200.8000000.3720001.142580NaN1.7060000.67048054model
2021_210.333333-0.3633331.200528NaN1.7466670.68603331model
2021_221.0000000.6700001.025046NaN1.6700000.61380011model
2021_230.000000-1.0000001.011686NaN1.6700000.60580010model
2021_241.0000000.7550001.155859NaN1.7550000.66237544model
\n", + "
" + ], + "text/plain": [ + " win profit exp_payoff exp_payoff_prec \\\n", + "bet_type match_week \n", + "goals_over_2.5 2021_19 0.818182 0.434545 1.193888 NaN \n", + " 2021_20 0.700000 0.144000 1.087417 NaN \n", + " 2021_21 0.800000 0.359000 1.130386 NaN \n", + " 2021_22 0.571429 0.040000 1.130597 NaN \n", + " 2021_23 0.500000 -0.140000 1.216788 NaN \n", + " 2021_24 0.625000 0.058750 1.168317 NaN \n", + " 2021_25 0.000000 -1.000000 1.200240 NaN \n", + "goals_under_2.5 2021_19 0.750000 0.255000 1.034973 NaN \n", + " 2021_20 0.800000 0.372000 1.142580 NaN \n", + " 2021_21 0.333333 -0.363333 1.200528 NaN \n", + " 2021_22 1.000000 0.670000 1.025046 NaN \n", + " 2021_23 0.000000 -1.000000 1.011686 NaN \n", + " 2021_24 1.000000 0.755000 1.155859 NaN \n", + "\n", + " odds confidence count buenas model \n", + "bet_type match_week \n", + "goals_over_2.5 2021_19 1.743636 0.683591 11 9 model \n", + " 2021_20 1.641000 0.664270 10 7 model \n", + " 2021_21 1.685000 0.671600 10 8 model \n", + " 2021_22 1.708571 0.662800 7 4 model \n", + " 2021_23 1.815000 0.667750 4 2 model \n", + " 2021_24 1.730000 0.674975 8 5 model \n", + " 2021_25 1.800000 0.666800 1 0 model \n", + "goals_under_2.5 2021_19 1.630000 0.634150 4 3 model \n", + " 2021_20 1.706000 0.670480 5 4 model \n", + " 2021_21 1.746667 0.686033 3 1 model \n", + " 2021_22 1.670000 0.613800 1 1 model \n", + " 2021_23 1.670000 0.605800 1 0 model \n", + " 2021_24 1.755000 0.662375 4 4 model " + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def show_results(df, groupby=[\"bet_type\", \"match_week\"]):\n", + " ix = np.logical_and(df[\"win\"]>=0, True)# df[\"label\"]>=1)\n", + " #ix = np.logical_and(df[\"consensus\"] >=0.1, ix)\n", + " ix2 = np.logical_and(df[\"odds\"]>=1.5, df[\"odds\"]<2.)\n", + " ix = np.logical_and(ix, ix2)\n", + " #ix = np.logical_and(ix, ~df[\"validation\"])\n", + " #ix = np.logical_and(ix, df[\"exp_payoff_prec\"] >0.88)\n", + " #ix = np.logical_and(ix, df[\"exp_payoff\"] <1.2)\n", + " #ix = np.logical_and(ix, df[\"exp_payoff\"] >0.8)\n", + " ix = np.logical_and(ix, df[\"confidence\"] >=0.60)\n", + " #ix = np.logical_and(ix, df[\"confidence\"] <=0.75)\n", + " x = df[ix].groupby(groupby)[[\"win\", \"profit\", \"exp_payoff\", \"exp_payoff_prec\", \"odds\", \"confidence\"]].mean()\n", + " x[\"count\"] = df[ix].groupby(groupby)[[\"win\"]].count()\n", + " x[\"buenas\"] = df[ix].groupby(groupby)[[\"win\"]].sum().astype(int)\n", + " x[\"model\"] = df[\"model\"].iloc[0]\n", + " return x\n", + "show_results(tips)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/setup.py b/setup.py index 4633506..d175ce8 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ setup( name="feature_selection", - description="This module allows the user to select the most relevant features of a dataset in order to use them in a machine learning project", + description="Feature-selection finds the most relevant features of a dataset to be used in a classification project.", long_description=long_description, long_description_content_type="text/markdown", packages=find_packages(),