{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59156,"databundleVersionId":13874099,"sourceType":"competition"}],"dockerImageVersionId":31153,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### 🔍 What the Code Does (Step by Step):\n\n1. **Finds the most common behavior** (e.g., `'sniff'`, `'approach'`, etc.) **across all training annotations**.\n   - It reads every labeled action from all training `.parquet` annotation files.\n   - Counts how often each action appears.\n   - Picks the **#1 most frequent action**.\n\n2. **Looks at the test video metadata** (from `test.csv`):\n   - Figures out **which mice are in the video** (mouse1, mouse2, etc.).\n   - Reads the field `behaviors_labeled`, which tells you **which agent→target pairs and actions are allowed** to be predicted (e.g., `\"mouse1,mouse2,approach\"`).\n\n3. **Converts that into actual mouse IDs**:\n   - For example, if `mouse1_id = 13` and `mouse2_id = 27`, then `\"mouse1 → mouse2\"` means **agent=13, target=27**.\n\n4. **Predicts the most common action** for **every allowed agent→target pair**, for the **entire duration** of the video:\n   - From frame `0` to the last frame (`fps × duration - 1`).\n   - One continuous segment per pair.\n\n5. **Formats this into the required submission format**:\n   ```\n   row_id,video_id,agent_id,target_id,action,start_frame,stop_frame\n   0,438887472,mouse1,mouse2,sniff,0,18440\n   1,438887472,mouse2,mouse1,sniff,0,18440\n   ...\n   ```\n\n6. **If something goes wrong**, it falls back to an **empty submission with correct columns** (so it doesn’t crash).\n\n\n\n### 🧠 In One Sentence:\n> This baseline **copies the most frequent behavior from the training data** and **applies it to all valid mouse pairs in the test video for the whole video duration**.\n","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport os\nimport glob\nfrom collections import Counter\n\nBASE_PATH = '/kaggle/input/MABe-mouse-behavior-detection'\n\n# Load metadata\ntrain_meta = pd.read_csv(os.path.join(BASE_PATH, 'train.csv'))\ntest_meta = pd.read_csv(os.path.join(BASE_PATH, 'test.csv'))\n\n# Load all training annotations to find the most common action\nannotation_files = glob.glob(os.path.join(BASE_PATH, 'train_annotation', '*', '*.parquet'))\nall_actions = []\n\nfor file in annotation_files:\n    df = pd.read_parquet(file)\n    all_actions.extend(df['action'].tolist())\n\n# Find the most frequent non-trivial action (ignore if 'no_action' were present, but it's not in annotations)\naction_counter = Counter(all_actions)\nmost_common_action = action_counter.most_common(1)[0][0]\nprint(f\"Most common action in training: {most_common_action}\")\n\n# Now generate submission for test set\nsubmission_rows = []\n\nfor _, test_row in test_meta.iterrows():\n    video_id = test_row['video_id']\n    \n    # Parse behaviors_labeled to get valid (agent, target, action_type) templates\n    # Example: '[\"mouse1,mouse2,approach\", \"mouse2,mouse1,sniff\"]'\n    behaviors_str = test_row['behaviors_labeled']\n    if pd.isna(behaviors_str) or behaviors_str == '[]':\n        # Fallback: assume all pairwise interactions among existing mice\n        mouse_cols = [col for col in test_meta.columns if col.startswith('mouse') and col.endswith('_id')]\n        mouse_ids = [int(test_row[col]) for col in mouse_cols if not pd.isna(test_row[col])]\n        # Generate all ordered pairs (including self)\n        pairs = [(a, b) for a in mouse_ids for b in mouse_ids]\n    else:\n        # Parse the string safely\n        import ast\n        try:\n            behavior_list = ast.literal_eval(behaviors_str)\n        except:\n            behavior_list = []\n        pairs = []\n        for item in behavior_list:\n            if isinstance(item, str):\n                parts = item.replace(\"'\", \"\").split(',')\n                if len(parts) == 3:\n                    agent_str, target_str, _ = parts\n                    # Map 'mouse1' -> actual mouse1_id, etc.\n                    agent_key = f\"{agent_str}_id\"\n                    target_key = f\"{target_str}_id\"\n                    if agent_key in test_row and target_key in test_row:\n                        aid = test_row[agent_key]\n                        tid = test_row[target_key]\n                        if not pd.isna(aid) and not pd.isna(tid):\n                            pairs.append((int(aid), int(tid)))\n        if not pairs:\n            # Fallback to all mice\n            mouse_cols = [col for col in test_meta.columns if col.startswith('mouse') and col.endswith('_id')]\n            mouse_ids = [int(test_row[col]) for col in mouse_cols if not pd.isna(test_row[col])]\n            pairs = [(a, b) for a in mouse_ids for b in mouse_ids]\n\n    # Total frames = fps * duration\n    total_frames = int(round(test_row['frames_per_second'] * test_row['video_duration_sec']))\n\n    # For each valid pair, output one long segment with the most common action\n    for agent_id, target_id in pairs:\n        # Convert numeric IDs back to 'mouse1', 'mouse2', etc.\n        agent_str = None\n        target_str = None\n        for i in range(1, 5):\n            if f'mouse{i}_id' in test_row and test_row[f'mouse{i}_id'] == agent_id:\n                agent_str = f'mouse{i}'\n            if f'mouse{i}_id' in test_row and test_row[f'mouse{i}_id'] == target_id:\n                target_str = f'mouse{i}'\n        if agent_str is None or target_str is None:\n            continue  # Skip if mapping fails\n\n        submission_rows.append({\n            'video_id': video_id,\n            'agent_id': agent_str,\n            'target_id': target_str,\n            'action': most_common_action,\n            'start_frame': 0,\n            'stop_frame': total_frames - 1  # inclusive\n        })\n\n# Create submission\nif submission_rows:\n    sub_df = pd.DataFrame(submission_rows)\n    sub_df['row_id'] = range(len(sub_df))\n    sub_df = sub_df[['row_id', 'video_id', 'agent_id', 'target_id', 'action', 'start_frame', 'stop_frame']]\nelse:\n    # Fallback to sample submission format\n    sample_sub = pd.read_csv(os.path.join(BASE_PATH, 'sample_submission.csv'))\n    sub_df = sample_sub.head(0)  # empty but correct schema\n\nsub_df.to_csv('submission.csv', index=False)\nprint(\"✅ Submission generated with\", len(sub_df), \"rows.\")\nprint(sub_df.head())","metadata":{"_uuid":"e6ceaadc-e530-45f1-8439-79523ca1b956","_cell_guid":"7bfe80fc-022d-402d-a882-d345deb8c7c9","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-10-22T05:31:51.124943Z","iopub.execute_input":"2025-10-22T05:31:51.125272Z","iopub.status.idle":"2025-10-22T05:31:53.702210Z","shell.execute_reply.started":"2025-10-22T05:31:51.125247Z","shell.execute_reply":"2025-10-22T05:31:53.701324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}