{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"sourceType":"competition"},{"sourceId":693317,"sourceType":"modelInstanceVersion","modelInstanceId":525734,"modelId":539796},{"sourceId":693340,"sourceType":"modelInstanceVersion","modelInstanceId":525756,"modelId":539818}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.501687Z","iopub.execute_input":"2025-12-20T14:11:45.502453Z","iopub.status.idle":"2025-12-20T14:11:45.674384Z","shell.execute_reply.started":"2025-12-20T14:11:45.502423Z","shell.execute_reply":"2025-12-20T14:11:45.673621Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\nKaggle Notebook for CSIRO Biomass Regression\n适配Kaggle平台的推理代码\n\"\"\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.675784Z","iopub.execute_input":"2025-12-20T14:11:45.676167Z","iopub.status.idle":"2025-12-20T14:11:45.680496Z","shell.execute_reply.started":"2025-12-20T14:11:45.676143Z","shell.execute_reply":"2025-12-20T14:11:45.679779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 1. 安装依赖库（如果需要）\n# ============================================================================\n# Kaggle环境通常已包含常用库，如需特定版本可取消注释\n# !pip install transformers==4.57.1\n# Kaggle环境已包含所需库，无需安装\n# !pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.681693Z","iopub.execute_input":"2025-12-20T14:11:45.681979Z","iopub.status.idle":"2025-12-20T14:11:45.696372Z","shell.execute_reply.started":"2025-12-20T14:11:45.681947Z","shell.execute_reply":"2025-12-20T14:11:45.695695Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 2. 导入库\n# ============================================================================\nimport pandas as pd\nimport numpy as np\nimport torch\nimport torchvision\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nfrom PIL import Image\nfrom transformers import Dinov2Model\nfrom tqdm import tqdm\nimport os","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.697978Z","iopub.execute_input":"2025-12-20T14:11:45.698480Z","iopub.status.idle":"2025-12-20T14:11:45.715706Z","shell.execute_reply.started":"2025-12-20T14:11:45.698457Z","shell.execute_reply":"2025-12-20T14:11:45.714986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 3. 配置\n# ============================================================================\n# 设置设备\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Using device: {device}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.716377Z","iopub.execute_input":"2025-12-20T14:11:45.716564Z","iopub.status.idle":"2025-12-20T14:11:45.729617Z","shell.execute_reply.started":"2025-12-20T14:11:45.716545Z","shell.execute_reply":"2025-12-20T14:11:45.729097Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 图像预处理参数\nmean = [0.485, 0.456, 0.406]\nstd = [0.229, 0.224, 0.225]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.730522Z","iopub.execute_input":"2025-12-20T14:11:45.730819Z","iopub.status.idle":"2025-12-20T14:11:45.743119Z","shell.execute_reply.started":"2025-12-20T14:11:45.730788Z","shell.execute_reply":"2025-12-20T14:11:45.742421Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 目标变量映射\nmapping = {\"Dry_Clover_g\": 0, \"Dry_Dead_g\": 1, \"Dry_Green_g\": 2, \"Dry_Total_g\": 3, \"GDM_g\": 4}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.743855Z","iopub.execute_input":"2025-12-20T14:11:45.744107Z","iopub.status.idle":"2025-12-20T14:11:45.757472Z","shell.execute_reply.started":"2025-12-20T14:11:45.744083Z","shell.execute_reply":"2025-12-20T14:11:45.756938Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"   # ============================================================================\n   # MLP模型架构（必须在加载模型之前定义）\n   # ============================================================================\n   class BiomassMLP(nn.Module):\n       def __init__(self, input_size, hidden_size=512, dropout_rate=0.3):\n           super(BiomassMLP, self).__init__()\n           self.network = nn.Sequential(\n               nn.Linear(input_size, hidden_size // 4),\n               nn.LeakyReLU(),\n               nn.Linear(hidden_size // 4, 1)\n           )\n       \n       def forward(self, x):\n           return torch.mean(torch.relu(self.network(x)), dim=(1, 2))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.758116Z","iopub.execute_input":"2025-12-20T14:11:45.758311Z","iopub.status.idle":"2025-12-20T14:11:45.774347Z","shell.execute_reply.started":"2025-12-20T14:11:45.758292Z","shell.execute_reply":"2025-12-20T14:11:45.773874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 4. Kaggle路径配置\n# ============================================================================\n# 数据路径（Kaggle会自动挂载到/kaggle/input/）\nDATA_ROOT = \"/kaggle/input/csiro-biomass\"\nMLP_ROOT = \"/kaggle/input/csiro-mlps-run1/pytorch/default/1\"\nDINOV2_MODEL_PATH = \"/kaggle/input/models/pytorch/default/1/models--facebook--dinov2-giant/snapshots/611a9d42f2335e0f921f1e313ad3c1b7178d206d\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.775038Z","iopub.execute_input":"2025-12-20T14:11:45.775295Z","iopub.status.idle":"2025-12-20T14:11:45.791180Z","shell.execute_reply.started":"2025-12-20T14:11:45.775274Z","shell.execute_reply":"2025-12-20T14:11:45.790702Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 5. 加载DINOv2模型\n# ============================================================================\nprint(\"Loading DINOv2 model...\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.793320Z","iopub.execute_input":"2025-12-20T14:11:45.793904Z","iopub.status.idle":"2025-12-20T14:11:45.811768Z","shell.execute_reply.started":"2025-12-20T14:11:45.793871Z","shell.execute_reply":"2025-12-20T14:11:45.810999Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Model path: {DINOV2_MODEL_PATH}\")\ntry:\n    model = Dinov2Model.from_pretrained(DINOV2_MODEL_PATH, local_files_only=True)\n    print(\"✅ Successfully loaded DINOv2 model.\")\nexcept Exception as e:\n    raise RuntimeError(f\"Failed to load DINOv2 model from {DINOV2_MODEL_PATH}. Please ensure the model dataset is attached. Error: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:45.812686Z","iopub.execute_input":"2025-12-20T14:11:45.813250Z","iopub.status.idle":"2025-12-20T14:11:46.231606Z","shell.execute_reply.started":"2025-12-20T14:11:45.813220Z","shell.execute_reply":"2025-12-20T14:11:46.230625Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.head = nn.Identity()\nmodel = model.to(device)\nmodel.eval()\nprint(\"DINOv2 model loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:46.232552Z","iopub.execute_input":"2025-12-20T14:11:46.232789Z","iopub.status.idle":"2025-12-20T14:11:47.559370Z","shell.execute_reply.started":"2025-12-20T14:11:46.232767Z","shell.execute_reply":"2025-12-20T14:11:47.558705Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 6. 加载训练好的MLP模型\n# ============================================================================\nprint(\"\\nLoading trained MLP models...\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.560156Z","iopub.execute_input":"2025-12-20T14:11:47.560387Z","iopub.status.idle":"2025-12-20T14:11:47.564407Z","shell.execute_reply.started":"2025-12-20T14:11:47.560361Z","shell.execute_reply":"2025-12-20T14:11:47.563759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"regressors = [[None for i in range(5)] for j in range(5)]\nselected_features = None\nscalers = None","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.565333Z","iopub.execute_input":"2025-12-20T14:11:47.565802Z","iopub.status.idle":"2025-12-20T14:11:47.583161Z","shell.execute_reply.started":"2025-12-20T14:11:47.565781Z","shell.execute_reply":"2025-12-20T14:11:47.582505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    for i in range(5):\n        for j in range(5):\n            model_path = os.path.join(MLP_ROOT, f\"target{i}/fold{j}.pt\")\n            if os.path.exists(model_path):\n                regressors[i][j] = torch.load(model_path, weights_only=False, map_location=device)\n            else:\n                print(f\"Warning: Model file not found: {model_path}\")\n    \n    import joblib\n    scaler_path = os.path.join(MLP_ROOT, \"sfs_scalers_run1.joblib\")\n    if os.path.exists(scaler_path):\n        (selected_features, scalers) = joblib.load(scaler_path)\n        print(\"✅ Loaded feature selectors and scalers.\")\n    else:\n        print(f\"Warning: Scaler file not found: {scaler_path}\")\n        selected_features, scalers = None, None\n    \n    print(\"✅ All MLP models loaded successfully.\")\nexcept Exception as e:\n    print(f\"Error loading models: {e}\")\n    raise","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.584016Z","iopub.execute_input":"2025-12-20T14:11:47.584690Z","iopub.status.idle":"2025-12-20T14:11:47.678282Z","shell.execute_reply.started":"2025-12-20T14:11:47.584655Z","shell.execute_reply":"2025-12-20T14:11:47.677598Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 7. 加载测试数据\n# ============================================================================\nprint(\"\\nLoading test data...\")\ntest_df = pd.read_csv(os.path.join(DATA_ROOT, \"test.csv\"))\nprint(f\"Loaded {len(test_df)} test samples\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.679247Z","iopub.execute_input":"2025-12-20T14:11:47.679678Z","iopub.status.idle":"2025-12-20T14:11:47.685582Z","shell.execute_reply.started":"2025-12-20T14:11:47.679643Z","shell.execute_reply":"2025-12-20T14:11:47.684881Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 8. 数据增强变换（与训练时一致）\n# ============================================================================\naugmentation_transforms = [\n    transforms.Compose([\n        transforms.ToTensor(), \n        transforms.Resize((224, 224)), \n        transforms.Normalize(mean, std), \n        torchvision.transforms.GaussianBlur(5)\n    ]),  # Original\n    transforms.Compose([\n        transforms.RandomHorizontalFlip(p=1.0), \n        transforms.ToTensor(), \n        transforms.Resize((224, 224)), \n        transforms.Normalize(mean, std), \n        torchvision.transforms.GaussianBlur(5)\n    ]),  # Horizontal flip\n    transforms.Compose([\n        transforms.RandomVerticalFlip(p=1.0), \n        transforms.ToTensor(), \n        transforms.Resize((224, 224)), \n        transforms.Normalize(mean, std), \n        torchvision.transforms.GaussianBlur(5)\n    ]),  # Vertical flip\n    transforms.Compose([\n        transforms.RandomHorizontalFlip(p=1.0), \n        transforms.RandomVerticalFlip(p=1.0), \n        transforms.ToTensor(), \n        transforms.Resize((224, 224)), \n        transforms.Normalize(mean, std), \n        torchvision.transforms.GaussianBlur(5)\n    ]),  # Both flips\n    transforms.Compose([\n        transforms.RandomRotation(degrees=90), \n        transforms.ToTensor(), \n        transforms.Resize((224, 224)), \n        transforms.Normalize(mean, std), \n        torchvision.transforms.GaussianBlur(5)\n    ]),  # 90 degree rotation\n    transforms.Compose([\n        transforms.RandomRotation(degrees=270), \n        transforms.ToTensor(), \n        transforms.Resize((224, 224)), \n        transforms.Normalize(mean, std), \n        torchvision.transforms.GaussianBlur(5)\n    ]),  # 270 degree rotation\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.686468Z","iopub.execute_input":"2025-12-20T14:11:47.686754Z","iopub.status.idle":"2025-12-20T14:11:47.699428Z","shell.execute_reply.started":"2025-12-20T14:11:47.686723Z","shell.execute_reply":"2025-12-20T14:11:47.698921Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 9. 提取测试图像特征\n# ============================================================================\nprint(\"\\nExtracting features from test images...\")\ntest_embeds = {}\nsample_ids_processed = []\ncounter = 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.700295Z","iopub.execute_input":"2025-12-20T14:11:47.700524Z","iopub.status.idle":"2025-12-20T14:11:47.720170Z","shell.execute_reply.started":"2025-12-20T14:11:47.700502Z","shell.execute_reply":"2025-12-20T14:11:47.719517Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i in tqdm(range(len(test_df))):\n    entry = test_df.iloc[i]\n    file_path = os.path.join(DATA_ROOT, entry['image_path'])\n    sample_id = entry['sample_id']\n    \n    # 只处理每个图像一次（多个目标共享同一图像）\n    img_id = sample_id.split(\"__\")[0]\n    if img_id not in sample_ids_processed:\n        image_embeddings = []\n        for aug in augmentation_transforms:\n            img = Image.open(file_path).convert('RGB')\n            x = aug(img).unsqueeze(0)\n            with torch.no_grad():\n                x = x.to(device)\n                # 提取特征（去掉CLS token，只保留patch tokens）\n                # 与原代码保持一致：torch.cat([model(x).last_hidden_state[:,1:,:].cpu()[0]]).unsqueeze(0)\n                features = model(x).last_hidden_state[:, 1:, :].cpu()[0]  # [num_patches, feature_dim]\n                image_embeddings.append(torch.cat([features]).unsqueeze(0))  # [1, num_patches, feature_dim]\n                counter += 1\n        \n        # 堆叠所有增强版本的特征: [num_aug, 1, num_patches, feature_dim]\n        # 与原代码保持一致，之后使用squeeze(1)变成[num_aug, num_patches, feature_dim]\n        test_embeds[img_id] = torch.stack(image_embeddings, dim=0)\n        sample_ids_processed.append(img_id)\n    \n    if counter % 100 == 0 and counter > 0:\n        print(f\"{counter} batches processed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:47.720992Z","iopub.execute_input":"2025-12-20T14:11:47.721205Z","iopub.status.idle":"2025-12-20T14:11:49.540382Z","shell.execute_reply.started":"2025-12-20T14:11:47.721185Z","shell.execute_reply":"2025-12-20T14:11:49.539697Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"✅ Extracted features from {len(test_embeds)} unique images\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.541412Z","iopub.execute_input":"2025-12-20T14:11:49.541689Z","iopub.status.idle":"2025-12-20T14:11:49.546193Z","shell.execute_reply.started":"2025-12-20T14:11:49.541658Z","shell.execute_reply":"2025-12-20T14:11:49.545609Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 10. 进行预测\n# ============================================================================\nprint(\"\\nMaking predictions...\")\npredictions = []\nsample_ids = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.546970Z","iopub.execute_input":"2025-12-20T14:11:49.547179Z","iopub.status.idle":"2025-12-20T14:11:49.561753Z","shell.execute_reply.started":"2025-12-20T14:11:49.547159Z","shell.execute_reply":"2025-12-20T14:11:49.560971Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i in tqdm(range(len(test_df)), desc=\"Predicting\"):\n    entry = test_df.iloc[i]\n    img_id = entry['sample_id'].split(\"__\")[0]\n    target_name = entry['sample_id'].split(\"__\")[1]\n    \n    # 获取图像特征（包含所有增强版本）\n    X = test_embeds[img_id]  # [num_aug, 1, num_patches, feature_dim]\n    sample_ids.append(entry['sample_id'])\n    \n    # 获取对应的模型列表（5个fold）\n    models = regressors[mapping[target_name]]\n    sfs = selected_features[mapping[target_name]] if selected_features else None\n    scaler_list = scalers[mapping[target_name]] if scalers else None\n    \n    # 对每个fold模型进行预测并平均\n    prediction = 0.0\n    model_count = 0\n    \n    for fold_idx, item in enumerate(models):\n        if item is None:\n            continue\n        \n        item.eval()\n        item = item.to(device)\n        \n        # 对每个增强版本进行预测，然后平均\n        # X shape: [num_aug, num_patches, feature_dim]\n        # 模型期望输入: [batch, num_patches, feature_dim]\n        with torch.no_grad():\n            # X已经是 [num_aug, num_patches, feature_dim]，可以直接使用\n            # 但原代码使用了squeeze(1)，这里保持与原代码一致\n            pred = item(X.squeeze(1).to(device))  # 输出: [num_aug]\n            # 对多个增强版本的预测取平均\n            single_pred = torch.mean(torch.relu(pred))\n        \n        if single_pred < 0.0:\n            single_pred = 0.0\n        \n        prediction += single_pred.cpu().item()\n        model_count += 1\n    \n    # 对所有fold模型的预测取平均\n    if model_count > 0:\n        prediction = prediction / model_count\n    else:\n        prediction = 0.0\n    \n    predictions.append(float(prediction))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.562582Z","iopub.execute_input":"2025-12-20T14:11:49.562910Z","iopub.status.idle":"2025-12-20T14:11:49.644342Z","shell.execute_reply.started":"2025-12-20T14:11:49.562889Z","shell.execute_reply":"2025-12-20T14:11:49.643692Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"✅ Completed predictions for {len(predictions)} samples\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.645156Z","iopub.execute_input":"2025-12-20T14:11:49.645401Z","iopub.status.idle":"2025-12-20T14:11:49.649046Z","shell.execute_reply.started":"2025-12-20T14:11:49.645377Z","shell.execute_reply":"2025-12-20T14:11:49.648492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================================\n# 11. 保存提交文件\n# ============================================================================\nprint(\"\\nSaving submission file...\")\nsubmission = pd.DataFrame({\n    'sample_id': sample_ids,\n    'target': predictions\n})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.649853Z","iopub.execute_input":"2025-12-20T14:11:49.650093Z","iopub.status.idle":"2025-12-20T14:11:49.663884Z","shell.execute_reply.started":"2025-12-20T14:11:49.650073Z","shell.execute_reply":"2025-12-20T14:11:49.663283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 保存到Kaggle工作目录\noutput_path = '/kaggle/working/submission.csv'\nsubmission.to_csv(output_path, index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.664729Z","iopub.execute_input":"2025-12-20T14:11:49.664942Z","iopub.status.idle":"2025-12-20T14:11:49.683341Z","shell.execute_reply.started":"2025-12-20T14:11:49.664922Z","shell.execute_reply":"2025-12-20T14:11:49.682673Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"=\"*60)\nprint(\"✅ Inference completed!\")\nprint(\"=\"*60)\nprint(f\"Submission file saved to: {output_path}\")\nprint(f\"Total predictions: {len(submission)}\")\nprint(\"\\nFirst 10 predictions:\")\nprint(submission.head(10))\nprint(\"\\nSubmission statistics:\")\nprint(submission['target'].describe())\nprint(\"=\"*60)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.684180Z","iopub.execute_input":"2025-12-20T14:11:49.684776Z","iopub.status.idle":"2025-12-20T14:11:49.700963Z","shell.execute_reply.started":"2025-12-20T14:11:49.684753Z","shell.execute_reply":"2025-12-20T14:11:49.700304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 显示最终文件\nsubmission","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T14:11:49.701722Z","iopub.execute_input":"2025-12-20T14:11:49.702004Z","iopub.status.idle":"2025-12-20T14:11:49.720935Z","shell.execute_reply.started":"2025-12-20T14:11:49.701968Z","shell.execute_reply":"2025-12-20T14:11:49.720316Z"}},"outputs":[],"execution_count":null}]}