Switch to unified view

a b/evaluation/Evaluation_Secondary.ipynb
1
{
2
 "cells": [
3
  {
4
   "cell_type": "code",
5
   "execution_count": null,
6
   "metadata": {},
7
   "outputs": [],
8
   "source": [
9
    "import json\n",
10
    "import pandas as pd\n",
11
    "import numpy as np\n",
12
    "import joblib\n",
13
    "import scipy\n",
14
    "import pickle\n",
15
    "import matplotlib.pyplot as plt"
16
   ]
17
  },
18
  {
19
   "cell_type": "code",
20
   "execution_count": null,
21
   "metadata": {},
22
   "outputs": [],
23
   "source": [
24
    "## This notebook assumes: \n",
25
    "#1: The loaded outcome is if the outcome happens ever, as opposed to the other evaluation, which was focused on the first 5 days\n",
26
    "#2: num_windows is the number of hours // 4 in which we want to make the triaging decision. Our default is making predictions using 48 hours of data to triage\n",
27
    "\n",
28
    "num_windows = 12"
29
   ]
30
  },
31
  {
32
   "cell_type": "code",
33
   "execution_count": null,
34
   "metadata": {},
35
   "outputs": [],
36
   "source": [
37
    "# Load models\n",
38
    "\n",
39
    "models_dict = joblib.load('models_dict.joblib')\n",
40
    "models_dict.keys()"
41
   ]
42
  },
43
  {
44
   "cell_type": "code",
45
   "execution_count": null,
46
   "metadata": {},
47
   "outputs": [],
48
   "source": [
49
    "### Read in sample cohort\n",
50
    "# Cohort should include those who did not have outcome within the first two days\n",
51
    "# Each individual should have exactly 12 windows\n",
52
    "# The outcome shoudl be whether deterioation occurred ever (not just within the first five days)\n",
53
    "\n",
54
    "df_cohort = pd.read_csv('sample_cohort_outcome_ever_past_2days.csv')\n",
55
    "\n",
56
    "# Remove windows after 2 days\n",
57
    "df_cohort = df_cohort[df_cohort['window_id'] < num_windows]\n",
58
    "\n",
59
    "# Remove incomplete windows\n",
60
    "df_cohort = df_cohort[df_cohort['window_id'] >= 1]\n",
61
    "\n",
62
    "test_hosp, test_window, test_y = df_cohort['hosp_id'], df_cohort['window_id'], df_cohort['y']\n",
63
    "\n",
64
    "cohort_IDs = df_cohort.set_index('ID')[[]]"
65
   ]
66
  },
67
  {
68
   "cell_type": "code",
69
   "execution_count": null,
70
   "metadata": {},
71
   "outputs": [],
72
   "source": [
73
    "len(np.unique(test_hosp))"
74
   ]
75
  },
76
  {
77
   "cell_type": "markdown",
78
   "metadata": {},
79
   "source": [
80
    "## M-CURES Model"
81
   ]
82
  },
83
  {
84
   "cell_type": "code",
85
   "execution_count": null,
86
   "metadata": {},
87
   "outputs": [],
88
   "source": [
89
    "mcures_clfs = models_dict['M-CURES']\n",
90
    "df_mcures = pd.read_csv('../preprocessing/sample_output/mcures.csv').set_index('ID')"
91
   ]
92
  },
93
  {
94
   "cell_type": "code",
95
   "execution_count": null,
96
   "metadata": {},
97
   "outputs": [],
98
   "source": [
99
    "# Calculate aggregated scores for all examples\n",
100
    "\n",
101
    "eval_matrix = scipy.sparse.csr_matrix(cohort_IDs.join(df_mcures).values.astype(float))\n",
102
    "all_y = np.array([clf.predict_proba(eval_matrix)[:,1] for clf in mcures_clfs])\n",
103
    "y_scores = all_y.mean(0)\n",
104
    "\n",
105
    "df_Yte_all = pd.DataFrame({'hosp_id': test_hosp, 'window_id': test_window, 'y': test_y, 'y_score': y_scores})\n",
106
    "df_Yte_agg = df_Yte_all.groupby('hosp_id').mean() #Can be changed to max, depending on how you want to aggregate scores"
107
   ]
108
  },
109
  {
110
   "cell_type": "code",
111
   "execution_count": null,
112
   "metadata": {},
113
   "outputs": [],
114
   "source": [
115
    "scores = np.sort(df_Yte_agg['y_score'])\n",
116
    "total_negs = df_Yte_agg['y']\n",
117
    "for s in scores: \n",
118
    "    curr = df_Yte_agg[df_Yte_agg['y_score'] <= s]\n",
119
    "    # How many people do we correctly flag with atleast an NPV of 0.95 (i.e. At most 5% of people we flagged have the event)\n",
120
    "    if 1 - curr['y'].mean() == 0.95: \n",
121
    "        curr_no_outcome = curr[curr['y'] == 0]\n",
122
    "        print('NPV: {:.2f}, Population % Flagged Correctly as Low-Risk {:.2%}'.format(1 - curr['y'].mean(), curr_no_outcome.shape[0] / len(scores)))\n",
123
    "        latest = curr"
124
   ]
125
  },
126
  {
127
   "cell_type": "markdown",
128
   "metadata": {},
129
   "source": [
130
    "## Sweep over NPV"
131
   ]
132
  },
133
  {
134
   "cell_type": "code",
135
   "execution_count": null,
136
   "metadata": {},
137
   "outputs": [],
138
   "source": [
139
    "# Plot the percentage of correctly flagged low-risk patients (true negatives) as NPV varies\n",
140
    "scores = np.sort(df_Yte_agg['y_score'])\n",
141
    "mcures_npvs = []\n",
142
    "mcures_flagged = []\n",
143
    "\n",
144
    "for s in scores: \n",
145
    "    curr = df_Yte_agg[df_Yte_agg['y_score'] <= s]\n",
146
    "    curr_no_outcome = curr[curr['y'] == 0]\n",
147
    "    mcures_npvs.append(1 - curr['y'].mean())\n",
148
    "    mcures_flagged.append(curr_no_outcome.shape[0] / len(scores))\n",
149
    "    \n",
150
    "fig, ax = plt.subplots(figsize=(3.5, 3.5))\n",
151
    "\n",
152
    "plt.plot(mcures_flagged, mcures_npvs, label = 'M-CURES Model', lw = 1.25)\n",
153
    "\n",
154
    "plt.xlabel('Percentage Correctly Flagged as Low-Risk')\n",
155
    "plt.ylabel('Negative Predictive Value')\n",
156
    "plt.show()"
157
   ]
158
  },
159
  {
160
   "cell_type": "code",
161
   "execution_count": null,
162
   "metadata": {},
163
   "outputs": [],
164
   "source": []
165
  }
166
 ],
167
 "metadata": {
168
  "kernelspec": {
169
   "display_name": "Python 3 (ipykernel)",
170
   "language": "python",
171
   "name": "python3"
172
  },
173
  "language_info": {
174
   "codemirror_mode": {
175
    "name": "ipython",
176
    "version": 3
177
   },
178
   "file_extension": ".py",
179
   "mimetype": "text/x-python",
180
   "name": "python",
181
   "nbconvert_exporter": "python",
182
   "pygments_lexer": "ipython3",
183
   "version": "3.9.7"
184
  }
185
 },
186
 "nbformat": 4,
187
 "nbformat_minor": 4
188
}