{"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":"Hi I trained Efficientnet_b4 with Group5Fold validation, the models are pretrained on Imagenet and selected on the best val_loss. \n\nMy code is based on [this code](https://www.kaggle.com/code/zzy990106/nfl-2-5d-cnn-baseline-inference) by [zzy](https://www.kaggle.com/zzy990106)\n\nHopefully this will help teams with few resources.\n\nHere is the code with the folds to give you an idea of the thresholds to use :","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport sys\nsys.path.append('/kaggle/input/timmmaster')\nimport timm\n\nfolder = \"/kaggle/input/nfl-player-contact-detection/\"\n\ndef expand_contact_id(df):\n    \"\"\"\n    Splits out contact_id into seperate columns.\n    \"\"\"\n    df[\"game_play\"] = df[\"contact_id\"].str[:12]\n    df[\"step\"] = df[\"contact_id\"].str.split(\"_\").str[-3].astype(\"int\")\n    df[\"nfl_player_id_1\"] = df[\"contact_id\"].str.split(\"_\").str[-2]\n    df[\"nfl_player_id_2\"] = df[\"contact_id\"].str.split(\"_\").str[-1]\n    return df\n\ntrain_labels = expand_contact_id(pd.read_csv(folder+\"train_labels.csv\")[[\"contact_id\",\"contact\"]])\ntrain_tracking = pd.read_csv(folder+\"train_player_tracking.csv\")\ntrain_helmets = pd.read_csv(folder+\"train_baseline_helmets.csv\")\ntrain_video_metadata = pd.read_csv(folder+\"train_video_metadata.csv\")\n\n\n\ndef create_features(df, tr_tracking, merge_col=\"step\", use_cols=[\"x_position\", \"y_position\"]):\n    output_cols = []\n    df_combo = (\n        df.astype({\"nfl_player_id_1\": \"str\"})\n        .merge(\n            tr_tracking.astype({\"nfl_player_id\": \"str\"})[\n                [\"game_play\", merge_col, \"nfl_player_id\",] + use_cols\n            ],\n            left_on=[\"game_play\", merge_col, \"nfl_player_id_1\"],\n            right_on=[\"game_play\", merge_col, \"nfl_player_id\"],\n            how=\"left\",\n        )\n        .rename(columns={c: c+\"_1\" for c in use_cols})\n        .drop(\"nfl_player_id\", axis=1)\n        .merge(\n            tr_tracking.astype({\"nfl_player_id\": \"str\"})[\n                [\"game_play\", merge_col, \"nfl_player_id\"] + use_cols\n            ],\n            left_on=[\"game_play\", merge_col, \"nfl_player_id_2\"],\n            right_on=[\"game_play\", merge_col, \"nfl_player_id\"],\n            how=\"left\",\n        )\n        .drop(\"nfl_player_id\", axis=1)\n        .rename(columns={c: c+\"_2\" for c in use_cols})\n        .sort_values([\"game_play\", merge_col, \"nfl_player_id_1\", \"nfl_player_id_2\"])\n        .reset_index(drop=True)\n    )\n    output_cols += [c+\"_1\" for c in use_cols]\n    output_cols += [c+\"_2\" for c in use_cols]\n    \n    if (\"x_position\" in use_cols) & (\"y_position\" in use_cols):\n        index = df_combo['x_position_2'].notnull()\n        \n        distance_arr = np.full(len(index), np.nan)\n        tmp_distance_arr = np.sqrt(\n            np.square(df_combo.loc[index, \"x_position_1\"] - df_combo.loc[index, \"x_position_2\"])\n            + np.square(df_combo.loc[index, \"y_position_1\"]- df_combo.loc[index, \"y_position_2\"])\n        )\n        \n        distance_arr[index] = tmp_distance_arr\n        df_combo['distance'] = distance_arr\n        output_cols += [\"distance\"]\n        \n    df_combo['G_flug'] = (df_combo['nfl_player_id_2']==\"G\")\n    output_cols += [\"G_flug\"]\n    return df_combo, output_cols\n\nuse_cols = [\n    'x_position', 'y_position', 'speed', 'distance',\n    'direction', 'orientation', 'acceleration', 'sa'\n]\n\ntreshold_dist = 2\ntrain, feature_cols = create_features(train_labels, train_tracking, use_cols=use_cols)\ntrain_filtered = train.query('distance<@treshold_dist').reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-02-07T19:37:44.032942Z","iopub.execute_input":"2023-02-07T19:37:44.033418Z","iopub.status.idle":"2023-02-07T19:39:22.994678Z","shell.execute_reply.started":"2023-02-07T19:37:44.033297Z","shell.execute_reply":"2023-02-07T19:39:22.992725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import GroupKFold\nfrom sklearn import preprocessing\n\nle = preprocessing.LabelEncoder()\ngroup = le.fit_transform(train_filtered[\"game_play\"])\n\ngroup_kfold = GroupKFold(n_splits=5)\n\nfor fold, (train_index, val_index) in enumerate(group_kfold.split(train_filtered, groups=group)):\n    # I trained on train_index & select on val_index\n\n    pass","metadata":{"execution":{"iopub.status.busy":"2023-02-07T19:39:22.997437Z","iopub.execute_input":"2023-02-07T19:39:22.998227Z","iopub.status.idle":"2023-02-07T19:39:23.673035Z","shell.execute_reply.started":"2023-02-07T19:39:22.998136Z","shell.execute_reply":"2023-02-07T19:39:23.670877Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch import nn\n\nclass Model(nn.Module):\n    def __init__(self):\n        super(Model, self).__init__()\n        self.backbone = timm.create_model('efficientnet_b4', pretrained=False, num_classes=500, in_chans=13)\n        self.mlp = nn.Sequential(\n            nn.Linear(18, 64),\n            nn.LayerNorm(64),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(64, 32),\n            nn.LayerNorm(32),\n        )\n        self.fc = nn.Linear(32+500*2, 1)\n\n    def forward(self, img, feature):\n        b, c, h, w = img.shape\n        img = img.reshape(b*2, c//2, h, w)\n        img = self.backbone(img).reshape(b, -1)\n        feature = self.mlp(feature)\n        y = nn.Sigmoid()(self.fc(torch.cat([img, feature], dim=1)))\n        return y","metadata":{"execution":{"iopub.status.busy":"2023-02-07T19:39:23.675020Z","iopub.execute_input":"2023-02-07T19:39:23.675579Z","iopub.status.idle":"2023-02-07T19:39:23.688609Z","shell.execute_reply.started":"2023-02-07T19:39:23.675524Z","shell.execute_reply":"2023-02-07T19:39:23.686863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model()\nPATH = \"/kaggle/input/nflefficientnet-b4/efficientnet_b4_fold_0.pt\"\nmodel.load_state_dict(torch.load(PATH,map_location=\"cpu\"))\n#\nmodel(torch.rand(5,26,256,256),torch.rand(5,18))","metadata":{"execution":{"iopub.status.busy":"2023-02-07T19:39:23.690769Z","iopub.execute_input":"2023-02-07T19:39:23.691425Z","iopub.status.idle":"2023-02-07T19:39:29.499902Z","shell.execute_reply.started":"2023-02-07T19:39:23.691385Z","shell.execute_reply":"2023-02-07T19:39:29.498603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Thanks for upvoting if it helped you as well as the [dataset](https://www.kaggle.com/datasets/thomasdubail/nflefficientnet-b4)","metadata":{}}]}