{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Model Training: Returns For Loss","metadata":{"_uuid":"9a099703-0437-4445-8152-859dacce81df","_cell_guid":"a4a79914-32b9-4ea4-aa20-f450c26e68bf","editable":true,"trusted":true}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom matplotlib.animation import FuncAnimation\nimport ipywidgets as widgets\nimport warnings\nimport datetime\nimport joblib\nimport json\nimport gc","metadata":{"_uuid":"a4cb2bed-02e4-4e32-a392-af2a561665d0","_cell_guid":"594d7305-c809-49a0-8495-13d5fd6636c3","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:42.913152Z","iopub.execute_input":"2022-01-06T22:41:42.913966Z","iopub.status.idle":"2022-01-06T22:41:42.920835Z","shell.execute_reply.started":"2022-01-06T22:41:42.913918Z","shell.execute_reply":"2022-01-06T22:41:42.919690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from typing import List, Dict, Set, Any, Callable, Optional\nfrom tqdm.notebook import tqdm\nfrom io import StringIO\nfrom IPython.display import HTML\nfrom timeit import default_timer as timer\nfrom collections import Counter","metadata":{"_uuid":"0a16d9a8-61fb-4fe0-95e3-3b55ba514b1a","_cell_guid":"0723a938-c29a-423d-9056-11d8c722a58b","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:42.922610Z","iopub.execute_input":"2022-01-06T22:41:42.923247Z","iopub.status.idle":"2022-01-06T22:41:42.937658Z","shell.execute_reply.started":"2022-01-06T22:41:42.923210Z","shell.execute_reply":"2022-01-06T22:41:42.936859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.exceptions import ConvergenceWarning\nfrom sklearn.dummy import DummyClassifier\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.svm import SVC\nfrom sklearn.metrics import plot_confusion_matrix\nfrom sklearn.metrics import (\n    accuracy_score,\n    precision_score,\n    recall_score,\n    f1_score,\n    roc_auc_score,\n)","metadata":{"_uuid":"e88835d1-a9f1-4086-85b3-2884d9387569","_cell_guid":"ccb00451-5451-4bca-b34d-c38e688f099d","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:42.939131Z","iopub.execute_input":"2022-01-06T22:41:42.939452Z","iopub.status.idle":"2022-01-06T22:41:42.954796Z","shell.execute_reply.started":"2022-01-06T22:41:42.939413Z","shell.execute_reply":"2022-01-06T22:41:42.953882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helpers","metadata":{"_uuid":"f9132073-05f7-461e-b574-03ea98833bff","_cell_guid":"2724edef-cd99-47fa-a700-c98a032562f0","editable":true,"trusted":true}},{"cell_type":"code","source":"def show_feature_dist_plots(fields, df):\n    n_rows = int(np.ceil(len(fields) / 2))\n    fig, axes = plt.subplots(n_rows, 2)\n\n    for (field, name), ax in zip(fields, axes.flatten()):\n        sns.histplot(df[field], ax=ax)\n        ax.axvline(0, color=\"black\", alpha=0.5, dashes=[1, 1])\n        ax.axhline(0, color=\"black\", alpha=0.5, dashes=[1, 1])\n        ax.set_xlabel(name)\n        ax.set_ylabel(\"Frequency\")\n\n    fig.set_size_inches(20, 5 * n_rows)\n    plt.show()\n\n\ndef show_scatter_plots(fields, df, Y, ylabel):\n    n_rows = int(np.ceil(len(fields) / 2))\n    fig, axes = plt.subplots(n_rows, 2)\n\n    for (field, name), ax in zip(fields, axes.flatten()):\n        sns.regplot(\n            x=df[field],\n            y=Y,\n            ax=ax,\n            line_kws=dict(\n                color=\"red\",\n                dashes=[9, 1]\n            ),\n            scatter_kws=dict(\n                s=5,\n                alpha=0.1,\n                color=\"blue\"\n            )\n        )\n        ax.axvline(0, color=\"black\", alpha=0.5, dashes=[1, 1])\n        ax.axhline(0, color=\"black\", alpha=0.5, dashes=[1, 1])\n        ax.set_xlabel(name)\n        ax.set_ylabel(ylabel)\n\n    fig.set_size_inches(20, 5 * n_rows)\n    plt.show()","metadata":{"_uuid":"22d402db-b273-4863-943c-8b396bacdfdb","_cell_guid":"18b5a871-7238-4fdb-b9e5-1949ac847bf3","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:42.956124Z","iopub.execute_input":"2022-01-06T22:41:42.956645Z","iopub.status.idle":"2022-01-06T22:41:42.971040Z","shell.execute_reply.started":"2022-01-06T22:41:42.956604Z","shell.execute_reply":"2022-01-06T22:41:42.969752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_regression_distribution(Y_vals, ax):\n    sns.histplot(Y_vals, ax=ax)\n    ax.set_xlim(-110, 110)\n    ax.set_xticks(np.arange(-110, 120, 10))\n    ax.set_xlabel(\"Return Yards Gained\")\n    ax.set_ylabel(\"Frequency\")","metadata":{"_uuid":"5610d76a-908e-40d4-a92b-7db8117ab84b","_cell_guid":"899a7290-4675-4120-85a4-7327cc27088e","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:42.973736Z","iopub.execute_input":"2022-01-06T22:41:42.974287Z","iopub.status.idle":"2022-01-06T22:41:42.989111Z","shell.execute_reply.started":"2022-01-06T22:41:42.974210Z","shell.execute_reply":"2022-01-06T22:41:42.988039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_binary_scores(Y_true, Y_pred):\n    acc = accuracy_score(Y_true, Y_pred)\n    prc = precision_score(Y_true, Y_pred)\n    rec = recall_score(Y_true, Y_pred)\n    f1s = f1_score(Y_true, Y_pred)\n    auc = roc_auc_score(Y_true, Y_pred)\n    print(f\"Accuracy  = {acc:.3f}\")\n    print(f\"Precision = {prc:.3f}\")\n    print(f\"Recall    = {rec:.3f}\")\n    print(f\"F1-Score  = {f1s:.3f}\")\n    print(f\"ROC AUC   = {auc:.3f}\")\n    print()\n\n\ndef plot_binary_dist(mdl, X, Yb, ax):\n    kw = dict(\n        binwidth=0.05,\n        binrange=(0, 1),\n        alpha=0.5,\n    )\n    sns.histplot(mdl.predict_proba(X[~Yb])[:,1], color=\"b\", label=\"Actual Gain\", ax=ax, **kw)\n    sns.histplot(mdl.predict_proba(X[Yb])[:,1], color=\"r\", label=\"Actual Loss\", ax=ax, **kw)\n    ax.legend()\n    ax.set_xlabel(\"Predicted Probability of Return For Zero or Loss\")\n\n\ndef plot_score_scatter(mdl, X, Yy, ax):\n    scatter_kws = dict(\n        alpha=0.1,\n    )\n    line_kws = dict(\n        color=\"blue\",\n    )\n    grid_kws = dict(\n        color=\"black\",\n        alpha=0.5,\n        dashes=[4, 1]\n    )\n    Ypb = mdl.predict(X)\n    Ppb = mdl.predict_proba(X)[:,1]\n    scatter_kws[\"color\"] = [\"red\" if pred_loss else \"green\" for pred_loss in Ypb]\n    sns.regplot(x=Ppb, y=Yy, color=\"b\", ax=ax, scatter_kws=scatter_kws, line_kws=line_kws)\n    ax.axhline(0, **grid_kws)\n    ax.set_xlabel(\"Predicted Probability of Return For Zero or Loss\")\n    ax.set_ylabel(\"Actual Return Yards Gained\")\n\n\ndef show_binary_plots(mdl, X, Yb, Yy):\n    fig, axes = plt.subplots(1, 3)\n    plot_binary_dist(mdl, X, Yb, ax=axes[0])\n    plot_score_scatter(mdl, X, Yy, ax=axes[1])\n    plot_confusion_matrix(mdl, X, Yb, ax=axes[2])\n    plt.gcf().set_size_inches(20, 4)\n    plt.show()\n\n\ndef evaluate_binary_model(mdl, X, Yb, Yy):\n    show_binary_scores(Yb, mdl.predict(X))\n    show_binary_plots(mdl, X, Yb, Yy)","metadata":{"_uuid":"463b4560-6229-4fde-b4c9-6a9ebc076a60","_cell_guid":"05787a09-b5f3-41a3-8a09-a51861e95b3a","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:42.990888Z","iopub.execute_input":"2022-01-06T22:41:42.991449Z","iopub.status.idle":"2022-01-06T22:41:43.010547Z","shell.execute_reply.started":"2022-01-06T22:41:42.991404Z","shell.execute_reply":"2022-01-06T22:41:43.009394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Data","metadata":{"_uuid":"642624fd-c826-4e96-8b25-fcb82246f72b","_cell_guid":"9febced7-7356-4685-9f61-295a0e21ae8b","editable":true,"trusted":true}},{"cell_type":"code","source":"DIR_VT = \"../input/process-punt-return-decision-data\"\ndf_return_frames = pd.read_csv(f\"{DIR_VT}/return_frames.csv\")\nprint(f\"Return frames has {df_return_frames.shape[0]:,d} rows and {df_return_frames.shape[1]:,d} cols.\")","metadata":{"_uuid":"d0edd2ca-ee46-4d85-9d40-a5ce2cefe02b","_cell_guid":"6564bd71-10f4-4363-9492-11d8f9e3c554","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:43.011956Z","iopub.execute_input":"2022-01-06T22:41:43.012264Z","iopub.status.idle":"2022-01-06T22:41:43.579706Z","shell.execute_reply.started":"2022-01-06T22:41:43.012228Z","shell.execute_reply":"2022-01-06T22:41:43.578836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_return_frames[\"players\"] = df_return_frames[\"players\"].apply(lambda j: json.loads(j))","metadata":{"_uuid":"11477be5-ba3f-4b2d-9747-f86c9e4ab5e8","_cell_guid":"020135a5-6842-461d-8955-f3baa64267dd","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:43.581322Z","iopub.execute_input":"2022-01-06T22:41:43.581729Z","iopub.status.idle":"2022-01-06T22:41:44.474998Z","shell.execute_reply.started":"2022-01-06T22:41:43.581683Z","shell.execute_reply":"2022-01-06T22:41:44.474297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DIR = \"../input/nfl-big-data-bowl-2022\"\ndf_games = pd.read_csv(f\"{DIR}/games.csv\")\ndf_players = pd.read_csv(f\"{DIR}/players.csv\")\n# Get patched versions from our custom output\ndf_plays = pd.read_csv(f\"{DIR_VT}/plays_patched.csv\")\ndf_pff = pd.read_csv(f\"{DIR_VT}/pff_patched.csv\")","metadata":{"_uuid":"8324de23-4ee5-4f3e-a4d1-86b51391744b","_cell_guid":"10171280-74ff-4df7-b74e-bb270c5b0252","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.476226Z","iopub.execute_input":"2022-01-06T22:41:44.477059Z","iopub.status.idle":"2022-01-06T22:41:44.642242Z","shell.execute_reply.started":"2022-01-06T22:41:44.477012Z","shell.execute_reply":"2022-01-06T22:41:44.641157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SEED = 0\nPLAY_KEYS = [\"gameId\", \"playId\"]\nFRAME_KEYS = [\n    \"gameId\",\n    \"playId\",\n    \"original\",\n    \"frameId\"\n]","metadata":{"_uuid":"d2b41cbe-0cf9-48eb-8c92-8ecf6cc0ee04","_cell_guid":"a1004d9b-4c9e-4f02-89d1-de51684d1572","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.643615Z","iopub.execute_input":"2022-01-06T22:41:44.643889Z","iopub.status.idle":"2022-01-06T22:41:44.648690Z","shell.execute_reply.started":"2022-01-06T22:41:44.643851Z","shell.execute_reply":"2022-01-06T22:41:44.647908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"_uuid":"d269172c-8e2c-43bd-b58d-af26aae310ec","_cell_guid":"c0213d21-b45a-49dc-8f15-f923a023d11e","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Check Data","metadata":{"_uuid":"eb00dc14-34a0-4ac6-ae64-c8a62cf9a365","_cell_guid":"bbbd4ecc-f235-4162-b423-f59bc84dab85","editable":true,"trusted":true}},{"cell_type":"code","source":"df_return_frames.columns","metadata":{"_uuid":"e5b5f52a-f927-490e-9ebb-3c72d288a364","_cell_guid":"41a48402-a587-4fa6-aa4e-057d11f53521","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.649920Z","iopub.execute_input":"2022-01-06T22:41:44.650450Z","iopub.status.idle":"2022-01-06T22:41:44.664734Z","shell.execute_reply.started":"2022-01-06T22:41:44.650413Z","shell.execute_reply":"2022-01-06T22:41:44.663704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_return_frames.firstReturnableEvent.value_counts()","metadata":{"_uuid":"72f5b799-0b53-4edb-a311-51685aeda25f","_cell_guid":"e3696909-8247-472d-9ba8-5ec28c2744e8","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.666358Z","iopub.execute_input":"2022-01-06T22:41:44.666904Z","iopub.status.idle":"2022-01-06T22:41:44.681298Z","shell.execute_reply.started":"2022-01-06T22:41:44.666861Z","shell.execute_reply":"2022-01-06T22:41:44.680506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_pre_return = df_return_frames[\n    (df_return_frames.firstReturnableEvent == \"punt_land\")\n    | (df_return_frames.firstReturnableEvent == \"punt_received\")\n    | (df_return_frames.firstReturnableEvent == \"punt_downed\")\n]\nlen(df_pre_return), len(df_return_frames)","metadata":{"_uuid":"d06d74e9-46d8-4daf-877f-b79c35e92957","_cell_guid":"3642dabd-f31e-4c35-80cb-e9434f256f1c","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.682754Z","iopub.execute_input":"2022-01-06T22:41:44.684431Z","iopub.status.idle":"2022-01-06T22:41:44.700823Z","shell.execute_reply.started":"2022-01-06T22:41:44.684385Z","shell.execute_reply":"2022-01-06T22:41:44.699809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_data = df_return_frames\n# df_data = df_pre_return.copy()\n# df_data = df_no_penalty_yards.copy()\nlen(df_data), len(df_return_frames)","metadata":{"_uuid":"5770038c-65a0-41c0-a9af-3e841db9b611","_cell_guid":"3e4f7919-bc25-4852-b048-93c26caacdd2","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.704387Z","iopub.execute_input":"2022-01-06T22:41:44.705030Z","iopub.status.idle":"2022-01-06T22:41:44.710132Z","shell.execute_reply.started":"2022-01-06T22:41:44.704988Z","shell.execute_reply":"2022-01-06T22:41:44.709548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Engineer Features","metadata":{"_uuid":"3c9fd08d-3fe3-4808-97c3-b06b970c29f8","_cell_guid":"0dd3d555-a6f6-4565-84f6-6188da69e1d3","editable":true,"trusted":true}},{"cell_type":"code","source":"MAX_DIST = 200\nSIDELINE_MIN = 0\nSIDELINE_MAX = 53.0 + (1.0 / 3.0)\nRECEIVING_GOAL_LINE = 10\nKICKING_GOAL_LINE = 110\n\n\ndef distance(a: Dict, b: Dict) -> float:\n    return np.sqrt((a[\"y\"] - b[\"y\"])**2 + (a[\"x\"] - b[\"x\"])**2)\n\n\ndef closest_defender_distance(\n    ball_x: float,\n    ball_y: float,\n    players: List[Dict],\n    kickingTeam: str\n) -> float:\n    ball = { \"x\": ball_x, \"y\": ball_y }\n    min_dist = MAX_DIST\n    for p in players:\n        if p[\"teamCode\"] == kickingTeam:\n            d = distance(ball, p)\n            if d < min_dist:\n                min_dist = d\n    return min_dist\n\n\ndef defenders_within_radius(\n    ball_x: float,\n    ball_y: float,\n    players: List[Dict],\n    kickingTeam: str,\n    radius: int\n) -> int:\n    ball = { \"x\": ball_x, \"y\": ball_y }\n    count = 0\n    for p in players:\n        if p[\"teamCode\"] == kickingTeam:\n            d = distance(ball, p)\n            if d < radius:\n                count += 1\n    return count\n\n\ndef blockers_within_radius(\n    ball_x: float,\n    ball_y: float,\n    players: List[Dict],\n    kickingTeam: str,\n    radius: int\n) -> int:\n    ball = { \"x\": ball_x, \"y\": ball_y }\n    count = 0\n    for p in players:\n        if p[\"teamCode\"] != kickingTeam and p[\"x\"] >= ball_x:\n            d = distance(ball, p)\n            if d < radius:\n                count += 1\n    return count\n\n\ndef distance_to_sideline(ball_y: float) -> float:\n    d_bottom = ball_y - SIDELINE_MIN\n    d_top = SIDELINE_MAX - ball_y\n    # Out of bounds\n    if d_bottom <= 0 or d_top <= 0:\n        return 0\n    # Get distance to closest sideline\n    return min(d_bottom, d_top)\n\n\ndef speed_upfield(player: Dict) -> float:\n    if pd.isna(player):\n        return 0\n    angle_rads = np.deg2rad(player[\"dir\"])\n    speed = player[\"s\"]\n    return speed * np.sin(angle_rads)\n\n\ndef speed_lateral(player: Dict) -> float:\n    if pd.isna(player):\n        return 0\n    angle_rads = np.deg2rad(player[\"dir\"])\n    speed = player[\"s\"]\n    # Take absolute value to get lateral speed in either direction\n    return speed * np.abs(np.cos(angle_rads))\n\n\ndef closest_defender_speed_upfield(\n    ball_x: float,\n    ball_y: float,\n    players: List[Dict],\n    kickingTeam: str\n) -> float:\n    ball = { \"x\": ball_x, \"y\": ball_y }\n    min_dist = MAX_DIST\n    closest = None\n    for p in players:\n        if p[\"teamCode\"] == kickingTeam:\n            d = distance(ball, p)\n            if d < min_dist:\n                min_dist = d\n                closest = p\n    return speed_upfield(closest)\n\n\ndef closest_defender_speed_lateral(\n    ball_x: float,\n    ball_y: float,\n    players: List[Dict],\n    kickingTeam: str\n) -> float:\n    ball = { \"x\": ball_x, \"y\": ball_y }\n    min_dist = MAX_DIST\n    closest = None\n    for p in players:\n        if p[\"teamCode\"] == kickingTeam:\n            d = distance(ball, p)\n            if d < min_dist:\n                min_dist = d\n                closest = p\n    return speed_lateral(closest)","metadata":{"_uuid":"a48a9387-8a90-460d-b9b3-7e34d61c6518","_cell_guid":"80270285-fae6-4dac-b94a-a7bcea04741f","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.711711Z","iopub.execute_input":"2022-01-06T22:41:44.712230Z","iopub.status.idle":"2022-01-06T22:41:44.735958Z","shell.execute_reply.started":"2022-01-06T22:41:44.712184Z","shell.execute_reply":"2022-01-06T22:41:44.734963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vec_closest_defender_distance = np.vectorize(closest_defender_distance)\nvec_defenders_within_radius = np.vectorize(defenders_within_radius)\nvec_blockers_within_radius = np.vectorize(blockers_within_radius)\nvec_distance_to_sideline = np.vectorize(distance_to_sideline)\nvec_closest_defender_speed_upfield = np.vectorize(closest_defender_speed_upfield)\nvec_closest_defender_speed_lateral = np.vectorize(closest_defender_speed_lateral)","metadata":{"_uuid":"08ec1590-1ef2-4b2f-8333-948520fb7c04","_cell_guid":"a1a3e413-085d-43a9-a6ce-21848f0cec90","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.737179Z","iopub.execute_input":"2022-01-06T22:41:44.737607Z","iopub.status.idle":"2022-01-06T22:41:44.752593Z","shell.execute_reply.started":"2022-01-06T22:41:44.737577Z","shell.execute_reply":"2022-01-06T22:41:44.751929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Main inputs\nbx = df_data[\"ballX\"]\nby = df_data[\"ballY\"]\np = df_data[\"players\"]\nkt = df_data[\"possessionTeam\"]","metadata":{"_uuid":"6a49032c-8666-4434-8461-c96aeff95740","_cell_guid":"f750af98-f5cc-48ce-9273-951c20f71e87","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.753853Z","iopub.execute_input":"2022-01-06T22:41:44.754658Z","iopub.status.idle":"2022-01-06T22:41:44.767037Z","shell.execute_reply.started":"2022-01-06T22:41:44.754605Z","shell.execute_reply":"2022-01-06T22:41:44.766373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Defender and blocker features\ndf_data[\"closestDefenderDistance\"] = vec_closest_defender_distance(bx, by, p, kt)\ndf_data[\"defendersWithinRadius\"] = vec_defenders_within_radius(bx, by, p, kt, 2)\ndf_data[\"blockersWithinRadius\"] = vec_blockers_within_radius(bx, by, p, kt, 5)","metadata":{"_uuid":"bfbe6ac8-67f6-43df-b6b5-4ad1b1e52a0f","_cell_guid":"d98d5248-a9e8-4124-8c55-1d9986204fb1","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:44.768254Z","iopub.execute_input":"2022-01-06T22:41:44.768805Z","iopub.status.idle":"2022-01-06T22:41:45.751316Z","shell.execute_reply.started":"2022-01-06T22:41:44.768765Z","shell.execute_reply":"2022-01-06T22:41:45.750386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Field position features\ndf_data[\"distanceToSideline\"] = vec_distance_to_sideline(by)\ndf_data[\"distanceToOwnGoalLine\"] = df_data[\"ballYardline\"]\ndf_data[\"isInsideOwnEndzone\"] = df_data[\"distanceToOwnGoalLine\"] <= 0\ndf_data[\"isInsideOwn20\"] = df_data[\"distanceToOwnGoalLine\"] <= 20\ndf_data[\"isInsideOwn10\"] = df_data[\"distanceToOwnGoalLine\"] <= 10","metadata":{"_uuid":"30666ad9-e143-437c-8734-a47d56741010","_cell_guid":"1d4e94b3-c1a4-47c0-8edc-32d60214b3a4","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:45.752580Z","iopub.execute_input":"2022-01-06T22:41:45.752827Z","iopub.status.idle":"2022-01-06T22:41:45.771127Z","shell.execute_reply.started":"2022-01-06T22:41:45.752798Z","shell.execute_reply":"2022-01-06T22:41:45.770232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Returner features\ndf_data[\"closestDefenderSpeedUpfield\"] = vec_closest_defender_speed_upfield(bx, by, p, kt)\ndf_data[\"closestDefenderSpeedLateral\"] = vec_closest_defender_speed_lateral(bx, by, p, kt)","metadata":{"_uuid":"1f998102-e94b-4148-b4c1-3bff63afb0df","_cell_guid":"fcfaa357-f6b6-4848-b237-562c791f01d2","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:45.773264Z","iopub.execute_input":"2022-01-06T22:41:45.773619Z","iopub.status.idle":"2022-01-06T22:41:46.628648Z","shell.execute_reply.started":"2022-01-06T22:41:45.773575Z","shell.execute_reply":"2022-01-06T22:41:46.627830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Split Cross Validation Data","metadata":{"_uuid":"753e62ad-d4d7-4077-9f5d-3dce1d400c4a","_cell_guid":"de5d70e4-f2d2-4f14-81f8-cbee0633434d","editable":true,"trusted":true}},{"cell_type":"code","source":"TARGET_VAL = \"returnYardsGained\"\nTARGET_BOOL = \"isZeroOrLoss\"","metadata":{"_uuid":"7890dc42-5cfb-46da-b509-b6cb8b9f3316","_cell_guid":"0b73841f-235a-4035-8893-f909c05c7857","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:46.629949Z","iopub.execute_input":"2022-01-06T22:41:46.630202Z","iopub.status.idle":"2022-01-06T22:41:46.634525Z","shell.execute_reply.started":"2022-01-06T22:41:46.630168Z","shell.execute_reply":"2022-01-06T22:41:46.633501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = df_data[df_data[\"split\"] == \"train\"]\ndf_validate = df_data[df_data[\"split\"] == \"validate\"]\ndf_test = df_data[df_data[\"split\"] == \"test\"]\nprint(f\"Train:    {len(df_train):,d} frames\")\nprint(f\"Validate: {len(df_validate):,d} frames\")\nprint(f\"Test:     {len(df_test):,d} frames\")\nprint()\nprint(f\"Train:    {(df_train[TARGET_BOOL].mean() * 100):.1f}% zero or loss\")\nprint(f\"Validate: {(df_validate[TARGET_BOOL].mean() * 100):.1f}% zero or loss\")\nprint(f\"Test:     {(df_test[TARGET_BOOL].mean() * 100):.1f}% zero or loss\")","metadata":{"_uuid":"a7037668-ebc5-4275-a5af-cce9b80a14e8","_cell_guid":"a2254381-8041-4d89-befd-cd22cdfd6bd3","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:46.636120Z","iopub.execute_input":"2022-01-06T22:41:46.636815Z","iopub.status.idle":"2022-01-06T22:41:46.765986Z","shell.execute_reply.started":"2022-01-06T22:41:46.636778Z","shell.execute_reply":"2022-01-06T22:41:46.765038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1, 3)\nplot_regression_distribution(df_train[TARGET_VAL], ax=axes[0])\nplot_regression_distribution(df_validate[TARGET_VAL], ax=axes[1])\nplot_regression_distribution(df_test[TARGET_VAL], ax=axes[2])\nfig.set_size_inches(20, 4)\nplt.show()","metadata":{"_uuid":"5124e897-8362-4c38-9629-45b56add8ed8","_cell_guid":"e196a075-50be-4b8f-b20b-33852deaba62","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:46.767427Z","iopub.execute_input":"2022-01-06T22:41:46.767810Z","iopub.status.idle":"2022-01-06T22:41:47.949261Z","shell.execute_reply.started":"2022-01-06T22:41:46.767764Z","shell.execute_reply":"2022-01-06T22:41:47.948320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Separate target variable from input variables for each split\n# All inputs are based on the decision frame\n\nINPUT_COLS = [\n    # Defender and blocker features\n    \"closestDefenderDistance\",\n    \"defendersWithinRadius\",\n    \"blockersWithinRadius\",\n    \"closestDefenderSpeedUpfield\",\n    \"closestDefenderSpeedLateral\",\n    # Field position features\n    \"ballYardline\",\n    \"distanceToSideline\",\n    \"isInsideOwnEndzone\",\n    \"isInsideOwn20\",\n    \"isInsideOwn10\",\n]\n\nYy_train = df_train[TARGET_VAL]\nYb_train = df_train[TARGET_BOOL]\nX_train = df_train[INPUT_COLS]\n\nYy_validate = df_validate[TARGET_VAL]\nYb_validate = df_validate[TARGET_BOOL]\nX_validate = df_validate[INPUT_COLS]\n\nYy_test = df_test[TARGET_VAL]\nYb_test = df_test[TARGET_BOOL]\nX_test = df_test[INPUT_COLS]","metadata":{"_uuid":"7cc06fd8-1d57-498e-9918-0f8a546d0094","_cell_guid":"bbb26e70-e9fc-4cc0-a97e-06188f2decef","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:47.952499Z","iopub.execute_input":"2022-01-06T22:41:47.952728Z","iopub.status.idle":"2022-01-06T22:41:47.962920Z","shell.execute_reply.started":"2022-01-06T22:41:47.952699Z","shell.execute_reply":"2022-01-06T22:41:47.961860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fields = [\n    (\"receivingYardline\", \"Receiving Yard Line\"),\n    (\"returnYardsGained\", \"Return Yards Gained\"),\n    \n    (\"kickLength\", \"Kick Length (yds)\"),\n    (\"ballYardline\", \"Ball Yard Line\"),\n    \n    (\"closestDefenderDistance\", \"Closest Defender Distance (yds)\"),\n    (\"distanceToSideline\", \"Distance To Sideline (yds)\"),\n    \n    (\"closestDefenderSpeedUpfield\", \"Closest Defender Speed Upfield (yds/sec)\"),\n    (\"closestDefenderSpeedLateral\", \"Closest Defender Speed Lateral (yds/sec)\"),\n    \n    (\"defendersWithinRadius\", \"Defenders Within Radius (players)\"),\n    (\"blockersWithinRadius\", \"Blockers Within Radius (players)\"),\n]","metadata":{"_uuid":"0e3a516b-be0b-444f-87fb-0e05d71abdf2","_cell_guid":"52942cff-e123-4b00-94ff-397d8d1d5f7e","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:47.964408Z","iopub.execute_input":"2022-01-06T22:41:47.965092Z","iopub.status.idle":"2022-01-06T22:41:47.980127Z","shell.execute_reply.started":"2022-01-06T22:41:47.965042Z","shell.execute_reply":"2022-01-06T22:41:47.979337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_feature_dist_plots(fields, df_train)","metadata":{"_uuid":"6210c47d-0f45-4792-bd18-275deef643fd","_cell_guid":"279f0a73-4e17-4559-8e40-050a37dea3e6","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:47.981389Z","iopub.execute_input":"2022-01-06T22:41:47.981811Z","iopub.status.idle":"2022-01-06T22:41:50.978529Z","shell.execute_reply.started":"2022-01-06T22:41:47.981776Z","shell.execute_reply":"2022-01-06T22:41:50.977944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_scatter_plots(fields, df_train, Yy_train, ylabel=\"Return Yards Gained\")","metadata":{"_uuid":"7b07d495-3862-4591-baaf-c5bbf7ba6cef","_cell_guid":"48aca214-6153-4dca-8430-193d34f332e4","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:50.979570Z","iopub.execute_input":"2022-01-06T22:41:50.980242Z","iopub.status.idle":"2022-01-06T22:41:56.147016Z","shell.execute_reply.started":"2022-01-06T22:41:50.980209Z","shell.execute_reply":"2022-01-06T22:41:56.146352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train Models","metadata":{"_uuid":"cd9e3574-db4c-405a-8418-6707ff8a7b49","_cell_guid":"024ffe47-2415-404c-877d-a95c0b6594c4","editable":true,"trusted":true}},{"cell_type":"code","source":"print(f\"Train:    {(df_train[TARGET_BOOL].mean() * 100):.1f}% zero or loss\")\nprint(f\"Validate: {(df_validate[TARGET_BOOL].mean() * 100):.1f}% zero or loss\")\nprint(f\"Test:     {(df_test[TARGET_BOOL].mean() * 100):.1f}% zero or loss\")","metadata":{"_uuid":"502c91c0-e23b-4880-9a5c-e74b7ecd186b","_cell_guid":"45d3880a-8fae-4adb-a6bb-4b09dc21a5ab","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:56.148109Z","iopub.execute_input":"2022-01-06T22:41:56.148455Z","iopub.status.idle":"2022-01-06T22:41:56.154910Z","shell.execute_reply.started":"2022-01-06T22:41:56.148418Z","shell.execute_reply":"2022-01-06T22:41:56.154203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Benchmark against naive model\ndummy_mdl = DummyClassifier(strategy=\"stratified\", random_state=SEED)\ndummy_mdl.fit(X_train, Yb_train)","metadata":{"_uuid":"48c55402-20c2-467a-bafb-67283eb5e9ea","_cell_guid":"856b10cf-295f-496f-8915-973f8bf55dc9","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:56.156077Z","iopub.execute_input":"2022-01-06T22:41:56.156435Z","iopub.status.idle":"2022-01-06T22:41:56.173971Z","shell.execute_reply.started":"2022-01-06T22:41:56.156405Z","shell.execute_reply":"2022-01-06T22:41:56.173337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_binary_model(dummy_mdl, X_validate, Yb_validate, Yy_validate)","metadata":{"_uuid":"3d47356a-ae41-4e94-a7c5-a7e20e274820","_cell_guid":"5489a15a-0267-47c4-9f1a-36b20076553b","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:56.175203Z","iopub.execute_input":"2022-01-06T22:41:56.175644Z","iopub.status.idle":"2022-01-06T22:41:57.171897Z","shell.execute_reply.started":"2022-01-06T22:41:56.175612Z","shell.execute_reply":"2022-01-06T22:41:57.170989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Benchmark against naive model\nshow_binary_scores(Yb_validate, [True for _ in Yb_validate])","metadata":{"_uuid":"f66b7d1d-3855-4120-946d-9d8942c834d1","_cell_guid":"a8475e8b-11dd-40fc-a798-0a04b9203708","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:57.173051Z","iopub.execute_input":"2022-01-06T22:41:57.173286Z","iopub.status.idle":"2022-01-06T22:41:57.195063Z","shell.execute_reply.started":"2022-01-06T22:41:57.173246Z","shell.execute_reply":"2022-01-06T22:41:57.194024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s = timer()\nmdl_lr = LogisticRegression(\n    penalty=\"l2\",\n    solver=\"saga\",\n    random_state=SEED,\n)\n# with warnings.catch_warnings():\n#     warnings.filterwarnings(\"ignore\", category=ConvergenceWarning)\nmdl_lr.fit(X_train, Yb_train)\nprint(f\"Trained model in {timer()-s:.1f} secs.\")","metadata":{"_uuid":"bd8b9db7-4bed-4558-b94b-1dbf2760c95c","_cell_guid":"57c6c426-0f62-40ec-b685-882fe6724bc8","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:57.196373Z","iopub.execute_input":"2022-01-06T22:41:57.196667Z","iopub.status.idle":"2022-01-06T22:41:57.297688Z","shell.execute_reply.started":"2022-01-06T22:41:57.196625Z","shell.execute_reply":"2022-01-06T22:41:57.296678Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_binary_model(mdl_lr, X_validate, Yb_validate, Yy_validate)","metadata":{"_uuid":"1dd1810d-e4b9-4d09-852b-b9464e6fd12b","_cell_guid":"588fc207-1a86-49c4-aae1-1ac11ee01a68","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:57.299025Z","iopub.execute_input":"2022-01-06T22:41:57.299345Z","iopub.status.idle":"2022-01-06T22:41:58.395846Z","shell.execute_reply.started":"2022-01-06T22:41:57.299302Z","shell.execute_reply":"2022-01-06T22:41:58.395303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s = timer()\nmdl_lr_bal = LogisticRegression(\n    penalty=\"l2\",\n    solver=\"saga\",\n    class_weight=\"balanced\",\n    random_state=SEED,\n)\nmdl_lr_bal.fit(X_train, Yb_train)\nprint(f\"Trained model in {timer()-s:.1f} secs.\")","metadata":{"_uuid":"174ffbb4-921b-4b1a-a21c-76e1a2e4dd0b","_cell_guid":"4f44a8b2-32e6-4f77-861e-046a2dfc6a71","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:58.398059Z","iopub.execute_input":"2022-01-06T22:41:58.398660Z","iopub.status.idle":"2022-01-06T22:41:58.498939Z","shell.execute_reply.started":"2022-01-06T22:41:58.398625Z","shell.execute_reply":"2022-01-06T22:41:58.498142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_binary_model(mdl_lr_bal, X_validate, Yb_validate, Yy_validate)","metadata":{"_uuid":"83369300-808c-4a7b-b010-451f8c66be76","_cell_guid":"e0ece3ea-1928-4016-b64c-848ec3d72583","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:58.500120Z","iopub.execute_input":"2022-01-06T22:41:58.500362Z","iopub.status.idle":"2022-01-06T22:41:59.888810Z","shell.execute_reply.started":"2022-01-06T22:41:58.500330Z","shell.execute_reply":"2022-01-06T22:41:59.887919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s = timer()\nmdl_rf = RandomForestClassifier(\n    n_estimators=100\n)\nmdl_rf.fit(X_train, Yb_train)\nprint(f\"Trained model in {timer()-s:.1f} secs.\")","metadata":{"_uuid":"6192067f-afd8-4fab-901a-cddc3322901f","_cell_guid":"df1d5cc7-8c4b-4701-8527-bbcd52f3d4b1","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:41:59.890138Z","iopub.execute_input":"2022-01-06T22:41:59.890370Z","iopub.status.idle":"2022-01-06T22:42:00.790082Z","shell.execute_reply.started":"2022-01-06T22:41:59.890343Z","shell.execute_reply":"2022-01-06T22:42:00.789486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_binary_model(mdl_rf, X_validate, Yb_validate, Yy_validate)","metadata":{"_uuid":"3ec93324-1093-4e72-9023-f6101d3df5de","_cell_guid":"69642457-6fd0-4051-8b6a-d21ec2b3a6aa","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:00.791120Z","iopub.execute_input":"2022-01-06T22:42:00.791546Z","iopub.status.idle":"2022-01-06T22:42:01.920762Z","shell.execute_reply.started":"2022-01-06T22:42:00.791504Z","shell.execute_reply":"2022-01-06T22:42:01.919918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s = timer()\nmdl_svc = SVC(\n    gamma=\"auto\",\n    probability=True\n)\nmdl_svc.fit(X_train, Yb_train)\nprint(f\"Trained model in {timer()-s:.1f} secs.\")","metadata":{"_uuid":"cd60f59e-0d60-4a93-81bf-1b4055b2c11a","_cell_guid":"22117102-7ccb-4a5e-9a6d-45be20702ad3","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:01.922178Z","iopub.execute_input":"2022-01-06T22:42:01.922400Z","iopub.status.idle":"2022-01-06T22:42:05.624969Z","shell.execute_reply.started":"2022-01-06T22:42:01.922373Z","shell.execute_reply":"2022-01-06T22:42:05.624030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"evaluate_binary_model(mdl_svc, X_validate, Yb_validate, Yy_validate)","metadata":{"_uuid":"cd45c028-a34d-42b6-90a8-28e419e21e4e","_cell_guid":"6c50b10c-b5a1-439e-bc88-904e695f8f77","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:05.626482Z","iopub.execute_input":"2022-01-06T22:42:05.626725Z","iopub.status.idle":"2022-01-06T22:42:07.597072Z","shell.execute_reply.started":"2022-01-06T22:42:05.626694Z","shell.execute_reply":"2022-01-06T22:42:07.596070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Output Predictions","metadata":{"_uuid":"73777392-6f69-4007-8704-d10c5e6f7343","_cell_guid":"dbb53d6e-32b7-4c61-898b-3ce27ef5cbca","editable":true,"trusted":true}},{"cell_type":"code","source":"def set_predictions_output(df, name, model):\n    X = df[INPUT_COLS]\n    df[f\"loss_{name}\"] = model.predict(X)\n    df[f\"prob_{name}\"] = model.predict_proba(X)[:,1]\n    return df\n\n\ndef save_models_and_predictions(df, models):\n    df_out = df[df.original].copy()\n    # Convert JSON columns to strings\n    df_out[\"players\"] = df_out[\"players\"].apply(lambda o: json.dumps(o))\n    # Go through each model\n    for (model_name, model) in tqdm(models):\n        # Save model\n        model_outfile = f\"models/{model_name}.joblib\"\n        joblib.dump(model, model_outfile)\n        print(f\"Saved model to file: {model_outfile}\")\n        # Add predictions to output\n        df_out = set_predictions_output(df_out, model_name, model)\n    # Save predictions\n    outfile = f\"predictions.csv\"\n    df_out.to_csv(outfile, index=False)\n    print(f\"Wrote {(df_out.shape[0]):,d} rows and {df_out.shape[1]} cols to file: {outfile}\")","metadata":{"_uuid":"46dfa580-6f18-405c-b5ce-5dbf1da3c139","_cell_guid":"07a93f2a-b915-452c-a7f0-f968fdaf475b","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:07.598547Z","iopub.execute_input":"2022-01-06T22:42:07.598871Z","iopub.status.idle":"2022-01-06T22:42:07.607890Z","shell.execute_reply.started":"2022-01-06T22:42:07.598827Z","shell.execute_reply":"2022-01-06T22:42:07.607335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p models","metadata":{"_uuid":"15859c47-498c-4648-8812-99aac910a36a","_cell_guid":"0dfc25ee-e5bf-4bba-9128-8ebbf327c252","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:07.611969Z","iopub.execute_input":"2022-01-06T22:42:07.612392Z","iopub.status.idle":"2022-01-06T22:42:08.403092Z","shell.execute_reply.started":"2022-01-06T22:42:07.612359Z","shell.execute_reply":"2022-01-06T22:42:08.401827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"chosen_models = [\n    (\"rf_binary\", mdl_rf),\n    (\"lr_binary\", mdl_lr),\n    (\"lr_bal_binary\", mdl_lr_bal),\n    (\"svc_binary\", mdl_svc),\n]","metadata":{"_uuid":"f1e1974a-2575-4ece-835a-7e56bd7d4526","_cell_guid":"54cc81d4-8412-4ab1-b2b6-ecafd22dae49","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:08.404742Z","iopub.execute_input":"2022-01-06T22:42:08.405013Z","iopub.status.idle":"2022-01-06T22:42:08.411229Z","shell.execute_reply.started":"2022-01-06T22:42:08.404980Z","shell.execute_reply":"2022-01-06T22:42:08.410077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"save_models_and_predictions(df_data, chosen_models)","metadata":{"_uuid":"d30a5ba2-3cb6-4aa1-8a46-4512c7f8676c","_cell_guid":"5fe98b1e-d0d2-4961-8c5a-c465624319ec","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-01-06T22:42:08.412923Z","iopub.execute_input":"2022-01-06T22:42:08.413189Z","iopub.status.idle":"2022-01-06T22:42:11.091678Z","shell.execute_reply.started":"2022-01-06T22:42:08.413160Z","shell.execute_reply":"2022-01-06T22:42:11.090799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"_uuid":"5e9b398f-489a-47a0-9986-ae76dafe7606","_cell_guid":"a701f689-b022-4274-8f0c-1f992b30877d","collapsed":false,"editable":true,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]}]}