{ "cells": [ { "cell_type": "markdown", "id": "7c726394-3d15-41d2-8425-360d89b7e88a", "metadata": {}, "source": [ "#### Interfacing with scikit-learn\n", "Using survivalpredict's pipeline to interface with the sklearn ecosystem.\n", "\n", "Survivalpredict's `SklearnSurvivalPipeline` class allows us to interface directly with scikit-learn's greater ecosystem. There is a whole ecosystem centered around hyperparameter tuning, feature selection, and scaling out compute for scikit-learn compatible code that we can interface with. " ] }, { "cell_type": "code", "execution_count": 1, "id": "eb50477c-b96d-4d73-90af-656a7c5fd9e9", "metadata": {}, "outputs": [], "source": [ "import warnings\n", "warnings.filterwarnings('ignore')\n", "\n", "import numpy as np\n", "import itertools\n", "import pandas as pd\n", "\n", "from sklearn.model_selection import GridSearchCV , cross_val_score\n", "from sklearn.compose import make_column_transformer, make_column_selector\n", "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", "\n", "from mlxtend.feature_selection import SequentialFeatureSelector\n", "from mlxtend.plotting import plot_sequential_feature_selection as plot_sfs\n", "\n", "from survivalpredict.estimators import CoxProportionalHazard,KaplanMeierSurvivalEstimator\n", "from survivalpredict.metrics import integrated_brier_score_administrative_sklearn_scorer \n", "from survivalpredict.pipeline import SklearnSurvivalPipeline,build_sklearn_pipeline_target,make_sklearn_survival_pipeline\n", "from survivalpredict.strata_preprocessing import StrataBuilderEncoder, StrataColumnTransformer, make_strata_column_transformer\n", "\n", "from SurvSet.data import SurvLoader\n", "loader = SurvLoader()" ] }, { "cell_type": "markdown", "id": "3d469ca7-e7de-4547-8efd-d9b72b6223f9", "metadata": {}, "source": [ "Let's start by loading in the data, using `SurvSet`. Notice that we are keeping the data as a dataframe. This allows us to retain feature names, enabling us to call out specific strata feature names when tuning for the best-performing strata." ] }, { "cell_type": "code", "execution_count": 2, "id": "ba37d084-091a-4c89-b33f-90b7872a06d1", "metadata": {}, "outputs": [], "source": [ "df = loader.load_dataset(\"support2\")[\"df\"]\n", "df = df.dropna()\n", "\n", "times = df[\"time\"].to_numpy().astype(np.int64)\n", "events = df[\"event\"].to_numpy().astype(np.bool_)\n", "X_df = df[list(set(df.columns).difference(set((\"pid\", \"event\", \"time\"))))]" ] }, { "cell_type": "markdown", "id": "fdd1245e-7fc4-4159-89d2-91e2d2c9cc20", "metadata": {}, "source": [ "Next, we are going to determine the maximum point in time to observe for evaluating the model. As time goes forward, a smaller and smaller percentage of individuals will still be in the study, including the tail-end points in the integrated Brier score, which will artificially inflate the score, not highlighting improvements in performance in points in time that include most individuals." ] }, { "cell_type": "code", "execution_count": 3, "id": "253f8c06-3b87-41b9-ad83-cf2df896e2b2", "metadata": {}, "outputs": [], "source": [ "max_time = np.percentile(times, 85).round().astype(np.int64)" ] }, { "cell_type": "markdown", "id": "72bd2699-5e58-4ea3-a73f-7c2c57bc71fb", "metadata": {}, "source": [ "The 'build_sklearn_pipeline_target' function allows us to take non-feature vectors, like `times`, `events`, `times_start`(for left censoring), and predetermined `strata` into a single vector that can be passed into scikit-learn classes. The output of 'build_sklearn_pipeline_target' will function as the 'y' vector for the SklearnSurvivalPipeline class.\n", "\n", "Next, we will build a pipeline that will turn 'fac_sex', 'fac_income' columns into the strata, then preprocess the rest of the features, and finally train a Cox model." ] }, { "cell_type": "code", "execution_count": 4, "id": "c455d769-e5c0-4400-804c-8ec0e045c994", "metadata": {}, "outputs": [], "source": [ "y = build_sklearn_pipeline_target(times, events)\n", "\n", "strata_transformers = make_strata_column_transformer(\n", " (StrataBuilderEncoder(), [\"fac_sex\", \"fac_income\"])\n", ")\n", "\n", "column_transformers = make_column_transformer(\n", " (StandardScaler(), make_column_selector(dtype_include=np.number)),\n", " (OneHotEncoder(), make_column_selector(dtype_include=[object, \"string\"])),\n", ")\n", "\n", "pipeline_cox = make_sklearn_survival_pipeline(\n", " strata_transformers,\n", " column_transformers,\n", " CoxProportionalHazard(),\n", " max_time=max_time,\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "id": "42351e79-b3c9-447d-b7de-33baed5db6af", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
SklearnSurvivalPipeline(max_time=818,\n",
       "                        steps=[('stratacolumntransformer',\n",
       "                                StrataColumnTransformer(strata_transformers=[('stratabuilderencoder',\n",
       "                                                                              StrataBuilderEncoder(),\n",
       "                                                                              ['fac_sex',\n",
       "                                                                               'fac_income'])],\n",
       "                                                        stratabuilderencoder__columns=['fac_sex',\n",
       "                                                                                       'fac_income'])),\n",
       "                               ('columntransformer',\n",
       "                                ColumnTransformer(transformers=[('standardscaler',\n",
       "                                                                 StandardScaler(),\n",
       "                                                                 <sklearn.compose._column_transformer.make_column_selector object at 0x7f9320e88440>),\n",
       "                                                                ('onehotencoder',\n",
       "                                                                 OneHotEncoder(),\n",
       "                                                                 <sklearn.compose._column_transformer.make_column_selector object at 0x7f9320fbdf90>)])),\n",
       "                               ('coxproportionalhazard',\n",
       "                                CoxProportionalHazard())])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "SklearnSurvivalPipeline(max_time=818,\n", " steps=[('stratacolumntransformer',\n", " StrataColumnTransformer(strata_transformers=[('stratabuilderencoder',\n", " StrataBuilderEncoder(),\n", " ['fac_sex',\n", " 'fac_income'])],\n", " stratabuilderencoder__columns=['fac_sex',\n", " 'fac_income'])),\n", " ('columntransformer',\n", " ColumnTransformer(transformers=[('standardscaler',\n", " StandardScaler(),\n", " ),\n", " ('onehotencoder',\n", " OneHotEncoder(),\n", " )])),\n", " ('coxproportionalhazard',\n", " CoxProportionalHazard())])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pipeline_cox" ] }, { "cell_type": "markdown", "id": "28b180be-19f1-4391-9520-186a45adb18c", "metadata": {}, "source": [ "We can now use sk's native cross_val_score, but we will need to pass in our own scorer" ] }, { "cell_type": "code", "execution_count": 6, "id": "0fbdf688-524e-4630-9274-4525ba1a1be9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-155.14165982224978)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(\n", " pipeline_cox,\n", " X_df,\n", " y,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", " error_score='raise',\n", ").mean()" ] }, { "cell_type": "code", "execution_count": 7, "id": "310c654f-2576-4887-bf3d-43fecf244b68", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-155.57987707062597)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#we can also build a cox model without strata\n", "\n", "cross_val_score(\n", " make_sklearn_survival_pipeline(\n", " column_transformers,\n", " CoxProportionalHazard(),\n", " max_time=max_time,\n", " ),\n", " X_df,\n", " y,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", ").mean()" ] }, { "cell_type": "markdown", "id": "cc5e2c8d-9d35-4e35-995e-56606dbc872e", "metadata": {}, "source": [ "Next, let's compare this score agaist our KaplanMeier baseline." ] }, { "cell_type": "code", "execution_count": 8, "id": "a6fa5427-6217-4405-8bce-3868c13319ba", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-179.90976086220107)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(\n", " make_sklearn_survival_pipeline(column_transformers,KaplanMeierSurvivalEstimator(),max_time=max_time),\n", " X_df,\n", " y,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", ").mean()" ] }, { "cell_type": "markdown", "id": "1fc174c2-3ab5-476c-980c-4810deeada54", "metadata": {}, "source": [ "It looks like our first Cox models are not bad, we are performing better than KaplanMeier. We can now start hyperparameters and strata tuning." ] }, { "cell_type": "code", "execution_count": 9, "id": "b4799e19-19ae-42d5-a5bd-a20afeb77c7f", "metadata": {}, "outputs": [], "source": [ "#getting combinations of all categorical data\n", "\n", "cat_cols = X_df.select_dtypes(pd.CategoricalDtype()).columns\n", "\n", "#in case we wana look at strata combinations\n", "cat_col_combinations = list(\n", " itertools.chain.from_iterable(\n", " itertools.combinations(cat_cols, i) for i in range(1, 3)\n", " )\n", ")\n", "\n", "#, this makes gridsearch run faster\n", "#cat_col_combinations = cat_cols \n" ] }, { "cell_type": "code", "execution_count": 10, "id": "e15a408a-506e-40fd-9b95-0b36f30cbb2b", "metadata": {}, "outputs": [], "source": [ "#you can take a look at all pram names and prameters with pipeline_cox.get_params()\n", "\n", "param_grid = {\n", " \"stratacolumntransformer__stratabuilderencoder__columns\": cat_col_combinations,\n", " \"coxproportionalhazard__alpha\": [0, 10, 25, 50, 75, 100],\n", "}" ] }, { "cell_type": "code", "execution_count": 11, "id": "9ba55490-1e21-4748-bcf3-544a05b566ab", "metadata": {}, "outputs": [], "source": [ "#running the sklearn native GridSearchCV, you can replace GridSearchCV with your favorite hyperprameter tunning class\n", "gs = GridSearchCV(\n", " pipeline_cox,\n", " param_grid,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", " n_jobs=5\n", ")\n", "\n" ] }, { "cell_type": "code", "execution_count": 12, "id": "9c8a8f60-13a8-479a-9c24-b7d528d8ffed", "metadata": {}, "outputs": [], "source": [ "#not all strata will be present in each cv split, this will cause errors/warnings; this should not be an issue, as sparse strata are not a good strata regardless\n", "import warnings\n", "\n", "with warnings.catch_warnings():\n", " warnings.simplefilter(\"ignore\")\n", "\n", " gs.fit(X_df, y)" ] }, { "cell_type": "code", "execution_count": 13, "id": "f4e7479c-42a2-4527-8e97-dbf559df7605", "metadata": {}, "outputs": [], "source": [ "cv_results = pd.DataFrame(gs.cv_results_)" ] }, { "cell_type": "code", "execution_count": 14, "id": "38c48fe6-b29e-49ea-abc3-d3616a22d8e6", "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", "
paramsmean_test_scorestd_test_scorerank_test_score
101{'coxproportionalhazard__alpha': 10, 'strataco...-119.8533155.1885381
68{'coxproportionalhazard__alpha': 10, 'strataco...-120.8935136.1710472
2{'coxproportionalhazard__alpha': 0, 'stratacol...-121.1890435.4956873
134{'coxproportionalhazard__alpha': 25, 'strataco...-121.2113707.2801294
233{'coxproportionalhazard__alpha': 50, 'strataco...-121.5804718.2438675
\n", "
" ], "text/plain": [ " params mean_test_score \\\n", "101 {'coxproportionalhazard__alpha': 10, 'strataco... -119.853315 \n", "68 {'coxproportionalhazard__alpha': 10, 'strataco... -120.893513 \n", "2 {'coxproportionalhazard__alpha': 0, 'stratacol... -121.189043 \n", "134 {'coxproportionalhazard__alpha': 25, 'strataco... -121.211370 \n", "233 {'coxproportionalhazard__alpha': 50, 'strataco... -121.580471 \n", "\n", " std_test_score rank_test_score \n", "101 5.188538 1 \n", "68 6.171047 2 \n", "2 5.495687 3 \n", "134 7.280129 4 \n", "233 8.243867 5 " ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cv_results.sort_values('rank_test_score').head(5)[['params','mean_test_score','std_test_score','rank_test_score']]" ] }, { "cell_type": "code", "execution_count": 15, "id": "94bbd3e7-1999-4051-a4ef-0787ca02c11a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'coxproportionalhazard__alpha': 10,\n", " 'stratacolumntransformer__stratabuilderencoder__columns': ('fac_sfdm2',\n", " 'fac_sex')}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#the 'best' parameters.\n", "cv_results[cv_results['rank_test_score'] == 1]['params'].values[0]\n" ] }, { "cell_type": "code", "execution_count": 16, "id": "c40922dd-bcce-41f8-ad1f-dc7f0bb15c00", "metadata": {}, "outputs": [], "source": [ "strata_transformers = make_strata_column_transformer(\n", " (StrataBuilderEncoder(), ('fac_sfdm2', 'fac_sex'))\n", ")\n", "\n", "sp_pipeline_cox = make_sklearn_survival_pipeline(\n", " strata_transformers,\n", " column_transformers,\n", " CoxProportionalHazard(alpha=10),\n", " max_time=max_time,\n", ")" ] }, { "cell_type": "markdown", "id": "abb8f634-46a2-4a57-b49a-c5a79346b68e", "metadata": {}, "source": [ "after tuning, we get a far better performing model." ] }, { "cell_type": "code", "execution_count": 17, "id": "50d17df6-5296-4f5f-8d95-8285a3967b8e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-119.8533147038668)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(\n", " sp_pipeline_cox,\n", " X_df,\n", " y,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", ").mean()" ] }, { "cell_type": "markdown", "id": "ff6b2c96-0573-4cca-931a-491b7ae8acd3", "metadata": {}, "source": [ "We are now going to experiment with feature selection." ] }, { "cell_type": "code", "execution_count": 18, "id": "0c364bdd-a4aa-4de4-9950-0819b0fbd331", "metadata": {}, "outputs": [], "source": [ "X_np = column_transformers.fit_transform(X_df)" ] }, { "cell_type": "code", "execution_count": 19, "id": "bb163f0f-18fa-4e6c-943d-7e50ff61ef50", "metadata": {}, "outputs": [], "source": [ "pipeline_cox2 = make_sklearn_survival_pipeline(\n", " CoxProportionalHazard(),\n", " max_time=max_time,\n", ")" ] }, { "cell_type": "code", "execution_count": 20, "id": "aba14ef3-4b4d-4809-bf67-8391677cd8c4", "metadata": {}, "outputs": [], "source": [ "sfs = SequentialFeatureSelector(pipeline_cox2, \n", " k_features= 1, \n", " forward=False, \n", " scoring=integrated_brier_score_administrative_sklearn_scorer, \n", " cv=5, \n", " n_jobs=5)" ] }, { "cell_type": "code", "execution_count": 21, "id": "3ab3f0fe-0ddb-467c-a2a2-f779316a31bf", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
SequentialFeatureSelector(estimator=SklearnSurvivalPipeline(max_time=818,\n",
       "                                                            steps=[('coxproportionalhazard',\n",
       "                                                                    CoxProportionalHazard())]),\n",
       "                          forward=False, k_features=(1, 1), n_jobs=5,\n",
       "                          scoring=make_scorer(integrated_brier_score_administrative_sklearn_metric, greater_is_better=False, response_method='predict'))
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "SequentialFeatureSelector(estimator=SklearnSurvivalPipeline(max_time=818,\n", " steps=[('coxproportionalhazard',\n", " CoxProportionalHazard())]),\n", " forward=False, k_features=(1, 1), n_jobs=5,\n", " scoring=make_scorer(integrated_brier_score_administrative_sklearn_metric, greater_is_better=False, response_method='predict'))" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sfs.fit(X_np,y)" ] }, { "cell_type": "code", "execution_count": 22, "id": "0d26d29b-f5fb-46ba-b1c1-2158c91fcba7", "metadata": {}, "outputs": [ { "data": { "image/png": "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iIiaYMsRERERURMMR0RERERNMBwRERERNcFwRERERNQEw1EC+PDDD3HCCScgPz8fkiTh5ZdfjrmsW2+9FQcffDCcTieys7Nx8sknY9OmTTGX9+CDD2L8+PGNi3FNnjwZb775ZszlNbVs2TJIkoR58+bFdP+bbroJkiQ1u4wePbpbddq5cyfOP/98ZGRkwGq1Yty4cfjyyy+7XM6QIUNa1E2SJMyZMyememmahgULFmDo0KGwWq0YPnw4Fi9e3Kk9glpTX1+PefPmYfDgwbBarZgyZQq++OKLTt23o9erEAILFy5EXl4erFYrpk+fjs2bN8dc3osvvogZM2YgIyMDkiRh/fr1MZUVDodx/fXXY9y4cbDb7cjPz8eFF16I0tLSmOt20003YfTo0bDb7UhLS8P06dOxbt26mMtr6rLLLoMkSbjrrrtiKmvWrFktXn8zZ87sVt02btyIE088ESkpKbDb7Tj44INRUlLS5bJae29IkoTbb789prp5PB5cccUVKCgogNVqxb777ouHHnoo5sdaUVGBWbNmIT8/HzabDTNnzmzzNdyZz9xAIIA5c+YgIyMDDocDp512GioqKmIq6x//+AemTZsGl8sFSZJQW1vb5uPsqLzq6mr88Y9/xKhRo2C1WlFUVIQrr7wSdXV1MT/W3//+9xg+fDisViuysrJw0kkn4ccff4yprCghBI455phunx+7guEoAXi9XkyYMAH3339/t8v64IMPMGfOHHz22WdYs2YNwuEwZsyYAa/XG1N5BQUFWLZsGb766it8+eWXOPLII3HSSSfhf//7X7fq+cUXX+Dvf/87xo8f361yxo4di7KyssbLRx99FHNZNTU1OOyww2A0GvHmm2/ihx9+wB133IG0tLQul/XFF180q9eaNWsAAGeccUZMdVu+fDkefPBB3Hfffdi4cSOWL1+O2267Dffee29M5V1yySVYs2YNnnjiCXz//feYMWMGpk+fjp07d3Z4345er7fddhvuuecePPTQQ1i3bh3sdjuKi4sRCARiKs/r9eI3v/kNli9f3q26+Xw+fP3111iwYAG+/vprvPjii9i0aRNOPPHEmB/rPvvsg/vuuw/ff/89PvroIwwZMgQzZszA7t27Yyov6qWXXsJnn32G/Pz8mOsGADNnzmz2OvzXv/4Vc3lbtmzBb37zG4wePRpr167Fd999hwULFsBisXS5rKZ1Kisrw2OPPQZJknDaaafFVLerr74ab731Fp588kls3LgR8+bNwxVXXIFXXnmly+UJIXDyySdj69at+M9//oNvvvkGgwcPxvTp01v9HO3MZ+5VV12FV199Fc899xw++OADlJaW4tRTT42pLJ/Ph5kzZ+LPf/5zq4+tK+WVlpaitLQUf/vb37BhwwasWrUKb731Fi6++OKYygOAAw88ECtXrsTGjRuxevVqCCEwY8YMaJrW5bKi7rrrrrhv19UhQQkFgHjppZfiVt6uXbsEAPHBBx/Ercy0tDTxyCOPxHz/+vp6MXLkSLFmzRoxdepUMXfu3JjKWbRokZgwYULM9djb9ddfL37zm9/Erbym5s6dK4YPHy50XY/p/scdd5yYPXt2s9tOPfVUcd5553W5LJ/PJxRFEa+99lqz2w844ABx4403dqmsvV+vuq6L3NxccfvttzfeVltbK8xms/jXv/7V5fKa2rZtmwAgvvnmm5jq1prPP/9cABC//vprXMqrq6sTAMQ777wTc3k7duwQgwYNEhs2bBCDBw8Wd955Z0xlXXTRReKkk07q8L6dLe+ss84S559/flzK2ttJJ50kjjzyyJjLGzt2rLjlllua3dbZ1/Pe5W3atEkAEBs2bGi8TdM0kZWVJR5++OEOy9v7M7e2tlYYjUbx3HPPNR6zceNGAUB8+umnXSqrqffff18AEDU1NR3WqTPlRT377LPCZDKJcDgcl/K+/fZbAUD8/PPPMZX1zTffiEGDBomysrK4nx/bw5ajfi7aPJqent7tsjRNwzPPPAOv14vJkyfHXM6cOXNw3HHHYfr06d2u0+bNm5Gfn49hw4bhvPPOa7WJv7NeeeUVHHTQQTjjjDOQnZ2NiRMn4uGHH+52HUOhEJ588knMnj075m8/U6ZMwbvvvouffvoJAPDtt9/io48+wjHHHNPlslRVhaZpLb7xW63WbrW8AcC2bdtQXl7e7LlNSUnBpEmT8Omnn3ar7J5QV1cHSZKQmpra7bJCoRD+8Y9/ICUlBRMmTIipDF3XccEFF+Daa6/F2LFju12ntWvXIjs7G6NGjcIf/vAHVFVVxVyv119/Hfvssw+Ki4uRnZ2NSZMmxaWLo6KiAq+//nqbrRWdMWXKFLzyyivYuXMnhBB4//338dNPP2HGjBldLisYDAJAs/eHLMswm82den/s/Zn71VdfIRwON3tPjB49GkVFRR2+J+L5+d3Z8urq6uByuWAwdLz1akfleb1erFy5EkOHDkVhYWGXy/L5fDj33HNx//33Izc3t8P6xBPDUT+m6zrmzZuHww47DPvtt1/M5Xz//fdwOBwwm8247LLL8NJLL2HfffeNqaxnnnkGX3/9NW699daY6xM1adKkxmbgBx98ENu2bcNvf/tb1NfXx1Te1q1b8eCDD2LkyJFYvXo1/vCHP+DKK6/E448/3q16vvzyy6itrcWsWbNiLmP+/Pk4++yzMXr0aBiNRkycOBHz5s3Deeed1+WynE4nJk+ejMWLF6O0tBSapuHJJ5/Ep59+irKyspjrCADl5eUAgJycnGa35+TkNP4uUQQCAVx//fU455xzurW55WuvvQaHwwGLxYI777wTa9asQWZmZkxlLV++HAaDAVdeeWXM9YmaOXMm/vnPf+Ldd9/F8uXL8cEHH+CYY45p0b3RGbt27YLH48GyZcswc+ZMvP322zjllFNw6qmn4oMPPuhWPR9//HE4nc5Wu5k6695778W+++6LgoICmEwmzJw5E/fffz8OP/zwLpcVDS433HADampqEAqFsHz5cuzYsaPD90drn7nl5eUwmUwtAnhH74l4fX53pbzKykosXrwYv/vd77pV3gMPPACHwwGHw4E333wTa9asgclk6nJZV111FaZMmYKTTjqpk48yfjqOhpS05syZgw0bNnS7NWDUqFFYv3496urq8Pzzz+Oiiy7CBx980OWAtH37dsydOxdr1qxpdZxCVzVtNRk/fjwmTZqEwYMH49lnn43pW6iu6zjooIOwdOlSAMDEiROxYcMGPPTQQ7joootiruejjz6KY445pt3xIx159tln8dRTT+Hpp5/G2LFjsX79esybNw/5+fkx1e2JJ57A7NmzMWjQICiKggMOOADnnHMOvvrqq5jrmEzC4TDOPPNMCCHw4IMPdqusI444AuvXr0dlZSUefvhhnHnmmVi3bh2ys7O7VM5XX32Fu+++G19//XVcxlecffbZjT+PGzcO48ePx/Dhw7F27VocddRRXSpL13UAwEknnYSrrroKALD//vvjk08+wUMPPYSpU6fGXM/HHnsM5513Xrc+E+6991589tlneOWVVzB48GB8+OGHmDNnDvLz87vcQm00GvHiiy/i4osvRnp6OhRFwfTp03HM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GlvZnn322WbHmEwmaJrW4r5ZWVkoKytrvL5582b4fL5265OTk4P8/Hxs3boV5513XpvHuVwunHXWWTjrrLNw+umnY+bMmaiurkZ6enq75RP1JwxHRNTCuHHjcN555+Gee+5pdvu0adOwe/du3HbbbTj99NPx1ltv4c0334TL5YrL/3v//fdj5MiRGDNmDO68807U1NRg9uzZAIA5c+bg4YcfxjnnnIPrrrsO6enp+Pnnn/HMM8/gkUceaWz96Ixrr70WixYtwvDhw7H//vtj5cqVWL9+feOMrnhYuHAhjj/+eBQVFeH000+HLMv49ttvsWHDBvz1r3/FiBEjEA6Hce+99+KEE05odQD5kCFD4PF48O6772LChAmw2Wyw2Ww48sgjcd9992Hy5MnQNA3XX399i5a51tx888248sorkZKSgpkzZyIYDOLLL79ETU0Nrr76aqxYsQJ5eXmYOHEiZFnGc889h9zcXK61RAMOZ6sRUatuueWWFt1eY8aMwQMPPID7778fEyZMwOeff96tsUl7W7ZsGZYtW4YJEybgo48+wiuvvILMzEwAaGzt0TQNM2bMwLhx4zBv3jykpqY2G9/UGVdeeSWuvvpqXHPNNRg3bhzeeustvPLKKxg5cmTcHktxcTFee+01vP322zj44INx6KGH4s4778TgwYMBABMmTMCKFSuwfPly7LfffnjqqadaTJufMmUKLrvsMpx11lnIysrCbbfdBgC44447UFhYiN/+9rc499xz8ac//alTY5QuueQSPPLII1i5ciXGjRuHqVOnYtWqVY3rMjmdTtx222046KCDcPDBB+OXX37BG2+80eW/L1Gyk8TeHddEREREAxi/DhARERE1wXBERERE1ATDEREREVETDEdERERETTAcERERETXBcERERETUBMMRERERURMMR0RERERNMBwRERERNcFwRERERNQEwxERERFRE/8Pn2VKiJtj8aEAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = plot_sfs(sfs.get_metric_dict(), kind='std_err')\n" ] }, { "cell_type": "code", "execution_count": 23, "id": "9dc46436-82d5-4561-a203-d91ffa6ca669", "metadata": {}, "outputs": [], "source": [ "step_wise_feature_selection_results = pd.DataFrame.from_records(sfs.subsets_).T" ] }, { "cell_type": "code", "execution_count": 24, "id": "35523dab-e0b0-4976-b4ab-288e9c165f92", "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", "
feature_idxcv_scoresavg_scorefeature_names
7(0, 3, 4, 15, 17, 18, 19)[-143.56667782179701, -136.25594055650689, -15...-144.112512(0, 3, 4, 15, 17, 18, 19)
6(0, 3, 4, 17, 18, 19)[-143.83516942714164, -135.87268885869483, -15...-144.263809(0, 3, 4, 17, 18, 19)
8(0, 1, 3, 4, 15, 17, 18, 19)[-141.46966297859967, -138.35774779284924, -15...-144.270329(0, 1, 3, 4, 15, 17, 18, 19)
9(0, 1, 3, 4, 15, 17, 18, 19, 23)[-149.19738821435038, -135.50584628943156, -15...-144.318642(0, 1, 3, 4, 15, 17, 18, 19, 23)
10(0, 1, 3, 4, 15, 16, 17, 18, 19, 23)[-149.00292841678186, -134.64053897377698, -15...-144.356467(0, 1, 3, 4, 15, 16, 17, 18, 19, 23)
\n", "
" ], "text/plain": [ " feature_idx \\\n", "7 (0, 3, 4, 15, 17, 18, 19) \n", "6 (0, 3, 4, 17, 18, 19) \n", "8 (0, 1, 3, 4, 15, 17, 18, 19) \n", "9 (0, 1, 3, 4, 15, 17, 18, 19, 23) \n", "10 (0, 1, 3, 4, 15, 16, 17, 18, 19, 23) \n", "\n", " cv_scores avg_score \\\n", "7 [-143.56667782179701, -136.25594055650689, -15... -144.112512 \n", "6 [-143.83516942714164, -135.87268885869483, -15... -144.263809 \n", "8 [-141.46966297859967, -138.35774779284924, -15... -144.270329 \n", "9 [-149.19738821435038, -135.50584628943156, -15... -144.318642 \n", "10 [-149.00292841678186, -134.64053897377698, -15... -144.356467 \n", "\n", " feature_names \n", "7 (0, 3, 4, 15, 17, 18, 19) \n", "6 (0, 3, 4, 17, 18, 19) \n", "8 (0, 1, 3, 4, 15, 17, 18, 19) \n", "9 (0, 1, 3, 4, 15, 17, 18, 19, 23) \n", "10 (0, 1, 3, 4, 15, 16, 17, 18, 19, 23) " ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "step_wise_feature_selection_results.sort_values('avg_score',ascending=False).head(5)" ] }, { "cell_type": "code", "execution_count": 25, "id": "af02d79a-c824-4d39-a538-c6a004bf2750", "metadata": {}, "outputs": [], "source": [ "best_features_idxs = list(step_wise_feature_selection_results.iloc[7]['feature_idx']) " ] }, { "cell_type": "code", "execution_count": 26, "id": "49b6194d-36f5-415b-b261-560ab91c4c7e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['standardscaler__num_hrt', 'standardscaler__num_surv2m',\n", " 'standardscaler__num_scoma', 'standardscaler__num_sps',\n", " 'standardscaler__num_adlp', 'standardscaler__num_adls',\n", " 'standardscaler__num_num_co', 'standardscaler__num_surv6m'],\n", " dtype=object)" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "best_features_names = column_transformers.get_feature_names_out()[list(best_features_idxs)]\n", "best_features_names" ] }, { "cell_type": "code", "execution_count": 27, "id": "3a60929e-d217-4162-9027-fa53ff53fbfb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-144.27032908030452)" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(\n", " pipeline_cox2,\n", " X_np[:,best_features_idxs],\n", " y,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", ").mean()" ] }, { "cell_type": "code", "execution_count": 28, "id": "f143a355-cd7a-417b-8597-be469ca8c6c3", "metadata": {}, "outputs": [], "source": [ "best_features_col_names = [i.split('__')[1] for i in column_transformers.get_feature_names_out()[list(best_features_idxs)]]\n", "strat_cols = ['fac_sfdm2', 'fac_sex']\n", "cols = best_features_col_names + strat_cols" ] }, { "cell_type": "code", "execution_count": 29, "id": "41a5eb8e-65d4-46b8-b670-1b6218c37109", "metadata": {}, "outputs": [], "source": [ "\n", "X_df2 = X_df[cols]\n", "\n", "\n", "strata_transformers = make_strata_column_transformer(\n", " (StrataBuilderEncoder(), strat_cols)\n", ")\n", "\n", "column_transformers = make_column_transformer(\n", " (StandardScaler(), best_features_col_names ),\n", ")\n", "\n", "pipeline_cox3 = make_sklearn_survival_pipeline(\n", " strata_transformers,\n", " column_transformers,\n", " CoxProportionalHazard(),\n", " max_time=max_time,\n", ")" ] }, { "cell_type": "markdown", "id": "0b80979d-90a7-4193-af9a-11a57099658a", "metadata": {}, "source": [ "Using both the best strata and best features, we are able to get the best performing model so far." ] }, { "cell_type": "code", "execution_count": 30, "id": "754124eb-41ee-42f9-aaf3-0e81d84e461f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(-112.16788210122328)" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(\n", " pipeline_cox3,\n", " X_df2,\n", " y,\n", " scoring=integrated_brier_score_administrative_sklearn_scorer,\n", ").mean()" ] }, { "cell_type": "code", "execution_count": null, "id": "1c8605fb-2692-45e4-b8ea-ed7b819f4b7f", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13.1" } }, "nbformat": 4, "nbformat_minor": 5 }