{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torchvision\nimport pandas as pd","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:34:21.203415Z","iopub.execute_input":"2026-07-19T14:34:21.204011Z","iopub.status.idle":"2026-07-19T14:34:21.207890Z","shell.execute_reply.started":"2026-07-19T14:34:21.203977Z","shell.execute_reply":"2026-07-19T14:34:21.207016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_val_data = pd.read_csv(r'/kaggle/input/competitions/classify-leaves/train.csv')\ntrain_val_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:34:24.148768Z","iopub.execute_input":"2026-07-19T14:34:24.149431Z","iopub.status.idle":"2026-07-19T14:34:24.185844Z","shell.execute_reply.started":"2026-07-19T14:34:24.149399Z","shell.execute_reply":"2026-07-19T14:34:24.184848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\n#标签转为0-175的整数\nlabel_encoder = LabelEncoder()\ntrain_val_data['label_id'] = label_encoder.fit_transform(train_val_data['label'])\n#类别数量\nlen(label_encoder.classes_)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:34:30.158062Z","iopub.execute_input":"2026-07-19T14:34:30.158837Z","iopub.status.idle":"2026-07-19T14:34:30.170110Z","shell.execute_reply.started":"2026-07-19T14:34:30.158802Z","shell.execute_reply":"2026-07-19T14:34:30.168979Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain_data,val_data = train_test_split(train_val_data,test_size=0.2,\n                                       random_state=42,shuffle=True,\n                                       stratify=train_val_data['label_id'])#按标签分层抽样","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:34:42.045509Z","iopub.execute_input":"2026-07-19T14:34:42.045994Z","iopub.status.idle":"2026-07-19T14:34:42.069688Z","shell.execute_reply.started":"2026-07-19T14:34:42.045963Z","shell.execute_reply":"2026-07-19T14:34:42.068717Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import PIL.Image\nimport torchvision.transforms.v2 as v2\nimport os\nfrom torch.utils.data import DataLoader,Dataset\n\nclass MyDataset(Dataset):\n    '''自定义数据集\n    原理在image-augmentation.ipynb里'''\n    def __init__(self,transforms,samples,main_path) -> None:\n        super().__init__()\n        #图片处理方法\n        self.transform = transforms\n        #图片名和标签,\n        #samples=[(name1,label1),(name2,label2),(name3,label3)]\n        self.samples = samples\n        #图片文件夹主路径\n        self.main_path = main_path\n\n    def __len__(self):\n        '''返回数据数量'''\n        return len(self.samples)\n    \n    def __getitem__(self, index):\n        '''根据索引返回对应样本和标签'''\n        image_name,label = self.samples[index]\n        #拼成完整的一张图片路径\n        image_path = os.path.join(self.main_path,image_name)\n        #打开图片加载为PIL.Image\n        with PIL.Image.open(image_path) as img:\n            image = img.convert('RGB')\n        #变为图片张量，做数据增强\n        image = self.transform(image)\n        #返回图片和标签\n        return image,int(label)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:34:49.148178Z","iopub.execute_input":"2026-07-19T14:34:49.148495Z","iopub.status.idle":"2026-07-19T14:34:49.156270Z","shell.execute_reply.started":"2026-07-19T14:34:49.148470Z","shell.execute_reply":"2026-07-19T14:34:49.155424Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\n\n#图片处理流程：训练数据和验证数据\ntrain_transforms = v2.Compose([\n    v2.ToImage(),\n    v2.RandomResizedCrop(size=(256,256),scale=(0.8,1),ratio=(0.5,2)),\n    v2.RandomHorizontalFlip(p=0.5),\n    v2.RandomVerticalFlip(p=0.5),\n    v2.ToDtype(dtype=torch.float32,scale=True),\n    v2.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])\n])\nval_transforms = v2.Compose([\n    v2.ToImage(),\n    v2.Resize((256,256)),\n    v2.ToDtype(dtype=torch.float32,scale=True),\n    v2.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])\n])\n\n\n#Dataset需要的samples格式\n#df -> ndarry -> list\n#只传图片和整数标签\ntrain_data = train_data[['image','label_id']].to_numpy().tolist()\n#train_data = train_data.tolist()\nval_data = val_data[['image','label_id']].to_numpy()\nval_data = val_data.tolist()\n\n#train_Dataset val_Dataset实例\nmain_path=r'/kaggle/input/competitions/classify-leaves'\ntrain_dataset = MyDataset(transforms=train_transforms,\n                          samples=train_data,\n                          main_path=main_path)\n\nval_dataset = MyDataset(transforms=val_transforms,\n                        samples=val_data,\n                        main_path=main_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:34:59.362857Z","iopub.execute_input":"2026-07-19T14:34:59.363318Z","iopub.status.idle":"2026-07-19T14:34:59.381993Z","shell.execute_reply.started":"2026-07-19T14:34:59.363287Z","shell.execute_reply":"2026-07-19T14:34:59.381032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#构造train_iter val_iter\nfrom torch.utils.data import DataLoader\n\nbatch_size = 256\ntrain_iter = DataLoader(dataset = train_dataset,batch_size=batch_size,\n                        shuffle=True,num_workers=4,)\n\nval_iter = DataLoader(dataset = val_dataset,batch_size=batch_size,\n                      shuffle=False,num_workers=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:35:03.792041Z","iopub.execute_input":"2026-07-19T14:35:03.792600Z","iopub.status.idle":"2026-07-19T14:35:03.801555Z","shell.execute_reply.started":"2026-07-19T14:35:03.792567Z","shell.execute_reply":"2026-07-19T14:35:03.800822Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.models import resnet34,ResNet34_Weights\n\n#加载预训练好的res34，参数使用默认的\nresnet34_pred = resnet34(weights = ResNet34_Weights.DEFAULT)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:35:15.645742Z","iopub.execute_input":"2026-07-19T14:35:15.646463Z","iopub.status.idle":"2026-07-19T14:35:16.065515Z","shell.execute_reply.started":"2026-07-19T14:35:15.646431Z","shell.execute_reply":"2026-07-19T14:35:16.064473Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(resnet34_pred.fc)\n#替换最后的分类类别数目\nresnet34_pred.fc = torch.nn.Linear(resnet34_pred.fc.in_features,176)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:35:31.803895Z","iopub.execute_input":"2026-07-19T14:35:31.804813Z","iopub.status.idle":"2026-07-19T14:35:31.811059Z","shell.execute_reply.started":"2026-07-19T14:35:31.804774Z","shell.execute_reply":"2026-07-19T14:35:31.809919Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#创建trainer,分类层的学习率设置为前面层的10倍\nnot_fc_layer = [param for name,param in resnet34_pred.named_parameters()\n                if name not in ['fc.weight','fc.bias']]\nlr = 0.0001\ntrainer = torch.optim.Adam([{'params': not_fc_layer,'lr': lr},#前面层\n                            {'params': resnet34_pred.fc.parameters(),'lr': 10*lr}],#输出层\n                            lr=lr)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T12:46:42.338721Z","iopub.execute_input":"2026-07-19T12:46:42.339177Z","iopub.status.idle":"2026-07-19T12:46:42.353444Z","shell.execute_reply.started":"2026-07-19T12:46:42.339150Z","shell.execute_reply":"2026-07-19T12:46:42.352473Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def acc(model,data_iter,device):\n    '''计算准确率'''\n    model.to(device)\n    model.eval()\n    right_samples = torch.tensor(0,device=device)\n    total_samples = 0\n    with torch.no_grad():\n        for x,y in data_iter:\n            x = x.to(device)\n            y = y.to(device)\n            \n            y_pre = model(x)\n            label_pre = y_pre.argmax(dim=1)\n            right_samples += torch.sum(label_pre==y)\n            total_samples += y_pre.shape[0]\n        acc = (right_samples/total_samples).item()\n    return acc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:35:39.901984Z","iopub.execute_input":"2026-07-19T14:35:39.902888Z","iopub.status.idle":"2026-07-19T14:35:39.908869Z","shell.execute_reply.started":"2026-07-19T14:35:39.902855Z","shell.execute_reply":"2026-07-19T14:35:39.907849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_once(train_iter,val_iter,model,num_epochs,trainer,device,model_save_path):\n    '''执行一次训练，引入早停机制'''\n    model.to(device)\n    loss = torch.nn.CrossEntropyLoss(reduction='mean')\n\n    train_acc=[]#每轮动态算一次\n    train_loss=[]#每轮算一次\n    val_acc=[]#每轮算一次\n\n    #早停相关变量初始化\n    best_val_acc = 0\n    best_epoch = 0\n     #最多几个epoch没提升就停止\n    patience = 3\n     #连续几个epoch没有提升\n    no_improve_count = 0\n\n    for epoch in range(num_epochs):\n        model.train()\n        right_samples = torch.tensor(0,device=device)\n        total_samples = 0\n        epoch_loss = torch.tensor(0.0,device=device)\n\n        for x,y in train_iter:\n            x = x.to(device)\n            y = y.to(device)\n\n            y_pre = model(x)\n            l = loss(y_pre,y)\n            trainer.zero_grad()\n            l.backward()\n            trainer.step()\n            \n            #计算train_loss,train_acc\n            with torch.no_grad():\n                label_pre = y_pre.argmax(dim=1)\n                right_samples += torch.sum(label_pre==y)\n                total_samples += y_pre.shape[0]\n                epoch_loss += l * y_pre.shape[0]\n    \n        #train_loss,train_acc\n        print(f'第{epoch+1}轮训练损失{(epoch_loss/total_samples).item()}')\n        train_loss.append((epoch_loss/total_samples).item())\n\n        print(f'第{epoch+1}轮训练acc{(right_samples/total_samples).item()}')\n        train_acc.append((right_samples/total_samples).item())\n\n        #val_acc\n        a = acc(model,val_iter,device)\n        print(f'第{epoch+1}轮测试acc{a}')\n        val_acc.append(a)\n\n        #早停部分\n        current_val_acc = a\n        if current_val_acc > best_val_acc:\n            best_val_acc = current_val_acc\n            best_epoch = epoch\n            no_improve_count = 0\n            #保存最好的模型参数\n            torch.save(model.state_dict(), model_save_path)\n            print(f\"保存最佳模型：epoch={best_epoch}, val_acc={best_val_acc:.4f}\")\n        #没有提升就记录一次no_improve_count\n        else:\n            no_improve_count += 1\n        #如果超过最多允许没提升的epoch数，就结束训练\n        if no_improve_count >= patience:\n            print(f\"提前停止。最佳结果：epoch={best_epoch},\"\n                  f\"val_acc={best_val_acc:.4f}\")\n            break\n\n    return train_loss,train_acc,val_acc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:35:46.738429Z","iopub.execute_input":"2026-07-19T14:35:46.739252Z","iopub.status.idle":"2026-07-19T14:35:46.749913Z","shell.execute_reply.started":"2026-07-19T14:35:46.739219Z","shell.execute_reply":"2026-07-19T14:35:46.749118Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loss,train_acc,val_acc=train_once(train_iter,val_iter,\n                                        model=resnet34_pred,\n                                        num_epochs=15,\n                                        trainer=trainer,\n                                        device=torch.device('cuda:0'),\n                                       model_save_path=\"/kaggle/working/best_resnet34_leaf.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T12:46:42.391581Z","iopub.execute_input":"2026-07-19T12:46:42.392431Z","iopub.status.idle":"2026-07-19T13:08:28.989415Z","shell.execute_reply.started":"2026-07-19T12:46:42.392402Z","shell.execute_reply":"2026-07-19T13:08:28.988209Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"训练结束后，加载早停保存的最佳模型","metadata":{}},{"cell_type":"code","source":"resnet34_pred.load_state_dict(\n    torch.load(\n        \"/kaggle/working/best_resnet34_leaf.pth\",\n        map_location=torch.device('cuda:0'),\n        weights_only=True,\n    )\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T13:08:28.991139Z","iopub.execute_input":"2026-07-19T13:08:28.991552Z","iopub.status.idle":"2026-07-19T13:08:29.133653Z","shell.execute_reply.started":"2026-07-19T13:08:28.991518Z","shell.execute_reply":"2026-07-19T13:08:29.132857Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"再原来的基础上继续训练，因为最后测试集acc抖动，可能是学习率过大，这次调小学习率","metadata":{}},{"cell_type":"code","source":"#创建trainer,分类层的学习率设置为前面层的10倍\nnot_fc_layer = [param for name,param in resnet34_pred.named_parameters()\n                if name not in ['fc.weight','fc.bias']]\nlr_2 = 0.00001\ntrainer_2 = torch.optim.Adam([{'params': not_fc_layer,'lr': lr_2},#前面层\n                            {'params': resnet34_pred.fc.parameters(),'lr': 10*lr_2}],#输出层\n                            lr=lr_2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T13:08:29.134621Z","iopub.execute_input":"2026-07-19T13:08:29.135029Z","iopub.status.idle":"2026-07-19T13:08:29.145307Z","shell.execute_reply.started":"2026-07-19T13:08:29.135004Z","shell.execute_reply":"2026-07-19T13:08:29.144372Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loss,train_acc,val_acc=train_once(train_iter,val_iter,\n                                        model=resnet34_pred,\n                                        num_epochs=5,\n                                        trainer=trainer_2,\n                                        device=torch.device('cuda:0'),\n                                       model_save_path=\"/kaggle/working/best_resnet34_leaf_2.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T13:08:29.146793Z","iopub.execute_input":"2026-07-19T13:08:29.147178Z","iopub.status.idle":"2026-07-19T13:17:40.263567Z","shell.execute_reply.started":"2026-07-19T13:08:29.147125Z","shell.execute_reply":"2026-07-19T13:17:40.262558Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"第三次训练：在第二次的基础上继续微调，这次在图片处理中加入随机旋转","metadata":{}},{"cell_type":"code","source":"#加载第二次训练的模型\nresnet34_pred.load_state_dict(\n    torch.load(\n        \"/kaggle/input/datasets/liuchendawang/67891/best_resnet34_leaf_2.pth\",\n        map_location=torch.device('cuda:0'),\n        weights_only=True,\n    )\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:54:12.905036Z","iopub.execute_input":"2026-07-19T14:54:12.905625Z","iopub.status.idle":"2026-07-19T14:54:13.029423Z","shell.execute_reply.started":"2026-07-19T14:54:12.905586Z","shell.execute_reply":"2026-07-19T14:54:13.028504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#第三次训练的处理流程，调小了裁剪时的宽高比，加入随机旋转\ntrain_transforms_3 = v2.Compose([\n    v2.ToImage(),\n    #在-15度到15度之间旋转\n    v2.RandomRotation(degrees=15,interpolation=v2.InterpolationMode.BILINEAR,\n                      fill=255),#旋转后四角用白色背景填充,\n    v2.RandomResizedCrop(size=(256,256),scale=(0.8,1),ratio=(0.7,1.3)),\n    v2.RandomHorizontalFlip(p=0.5),\n    v2.RandomVerticalFlip(p=0.5),\n    v2.ToDtype(dtype=torch.float32,scale=True),\n    v2.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:54:15.145129Z","iopub.execute_input":"2026-07-19T14:54:15.145481Z","iopub.status.idle":"2026-07-19T14:54:15.152842Z","shell.execute_reply.started":"2026-07-19T14:54:15.145452Z","shell.execute_reply":"2026-07-19T14:54:15.151860Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#重新创建train_dataset\ntrain_dataset_3 = MyDataset(transforms=train_transforms_3,\n                          samples=train_data,\n                          main_path=main_path)\n\n#重新创建train_iter\nfrom torch.utils.data import DataLoader\n\nbatch_size = 128\ntrain_iter_3 = DataLoader(dataset = train_dataset_3,batch_size=batch_size,\n                        shuffle=True,num_workers=0,)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:54:20.035334Z","iopub.execute_input":"2026-07-19T14:54:20.035831Z","iopub.status.idle":"2026-07-19T14:54:20.041179Z","shell.execute_reply.started":"2026-07-19T14:54:20.035793Z","shell.execute_reply":"2026-07-19T14:54:20.040170Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#新建trainer\nnot_fc_layer = [param for name,param in resnet34_pred.named_parameters()\n                if name not in ['fc.weight','fc.bias']]\nlr_3 = 0.00001\ntrainer_3 = torch.optim.Adam([{'params': not_fc_layer,'lr': lr_3},#前面层\n                            {'params': resnet34_pred.fc.parameters(),'lr': 10*lr_3}],#输出层\n                            lr=lr_3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:54:26.956561Z","iopub.execute_input":"2026-07-19T14:54:26.956868Z","iopub.status.idle":"2026-07-19T14:54:26.963329Z","shell.execute_reply.started":"2026-07-19T14:54:26.956842Z","shell.execute_reply":"2026-07-19T14:54:26.962173Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#执行第三次训练\ntrain_loss,train_acc,val_acc=train_once(train_iter_3,val_iter,\n                                        model=resnet34_pred,\n                                        num_epochs=5,\n                                        trainer=trainer_3,\n                                        device=torch.device('cuda:0'),\n                                       model_save_path=\"/kaggle/working/best_resnet34_leaf_3.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T14:54:29.659469Z","iopub.execute_input":"2026-07-19T14:54:29.659897Z","iopub.status.idle":"2026-07-19T15:02:17.659960Z","shell.execute_reply.started":"2026-07-19T14:54:29.659869Z","shell.execute_reply":"2026-07-19T15:02:17.658768Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"预测","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport PIL.Image\nimport torch\n\nfrom torch.utils.data import Dataset, DataLoader\n\n\nclass MyTestDataset(Dataset):\n    \"\"\"无标签测试数据集\"\"\"\n\n    def __init__(\n        self,\n        transforms,\n        image_names,\n        main_path,\n    ):\n        super().__init__()\n\n        self.transform = transforms\n        self.image_names = image_names\n        self.main_path = main_path\n\n    def __len__(self):\n        return len(self.image_names)\n\n    def __getitem__(self, index):\n        image_name = self.image_names[index]\n\n        image_path = os.path.join(\n            self.main_path,\n            image_name,\n        )\n\n        with PIL.Image.open(image_path) as img:\n            image = img.convert(\"RGB\")\n\n        image = self.transform(image)\n\n        return image\n\n\n# ---------------------------\n# 读取测试集\n# ---------------------------\n\ntest_csv_path = \"/kaggle/input/competitions/classify-leaves/test.csv\"\n\ntest_df = pd.read_csv(test_csv_path)\n\ntest_image_names = test_df[\"image\"].tolist()\n\ntest_dataset = MyTestDataset(\n    transforms=val_transforms,\n    image_names=test_image_names,\n    main_path=main_path,\n)\n\ntest_iter = DataLoader(\n    test_dataset,\n    batch_size=256,\n    shuffle=False,\n    num_workers=4,\n    pin_memory=True,\n)\n\n\n# ---------------------------\n# 加载第二阶段最佳模型\n# ---------------------------\n\ndevice = torch.device(\n    \"cuda:0\" if torch.cuda.is_available() else \"cpu\"\n)\n\nsecond_model_path = (\n    \"/kaggle/input/datasets/liuchendawang/67891/best_resnet34_leaf_2.pth\"\n)\n\nstate_dict = torch.load(\n    second_model_path,\n    map_location=device,\n    weights_only=True,\n)\n\nresnet34_pred.load_state_dict(state_dict)\nresnet34_pred.to(device)\nresnet34_pred.eval()\n\n\n# ---------------------------\n# 预测\n# ---------------------------\n\nresult = []\n\nwith torch.inference_mode():\n    for x in test_iter:\n        x = x.to(\n            device,\n            non_blocking=True,\n        )\n\n        y_pre = resnet34_pred(x)\n        label_pre = y_pre.argmax(dim=1)\n\n        result.extend(\n            label_pre.cpu().tolist()\n        )\n\nresult = np.asarray(\n    result,\n    dtype=np.int64,\n)\n\nassert len(result) == len(test_df)\n\n\n# ---------------------------\n# 整数标签转回字符串\n# ---------------------------\n\npredicted_labels = label_encoder.inverse_transform(\n    result\n)\n\n\n# ---------------------------\n# 生成提交文件\n# ---------------------------\n\nsubmission = pd.DataFrame({\n    \"image\": test_df[\"image\"],\n    \"label\": predicted_labels,\n})\n\nsubmission_path = \"/kaggle/working/submission.csv\"\n\nsubmission.to_csv(\n    submission_path,\n    index=False,\n)\n\nprint(submission.head())\nprint(submission.shape)\nprint(\"提交文件路径：\", submission_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-07-19T15:32:20.554500Z","iopub.execute_input":"2026-07-19T15:32:20.555259Z","iopub.status.idle":"2026-07-19T15:33:03.228176Z","shell.execute_reply.started":"2026-07-19T15:32:20.555221Z","shell.execute_reply":"2026-07-19T15:33:03.226828Z"}},"outputs":[],"execution_count":null}]}