{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"},{"sourceId":327657,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":274989,"modelId":295877},{"sourceId":327661,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":274992,"modelId":295880}],"dockerImageVersionId":30919,"isInternetEnabled":true,"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-04-08T11:49:02.667564Z","iopub.execute_input":"2025-04-08T11:49:02.667998Z","iopub.status.idle":"2025-04-08T11:49:35.128640Z","shell.execute_reply.started":"2025-04-08T11:49:02.667974Z","shell.execute_reply":"2025-04-08T11:49:35.127754Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import train_test_split\n\n# 可视化\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# PyTorch\n\nimport torch as T\nfrom torch import nn\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import models\nfrom torchvision import transforms","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:35.129899Z","iopub.execute_input":"2025-04-08T11:49:35.130382Z","iopub.status.idle":"2025-04-08T11:49:38.485925Z","shell.execute_reply.started":"2025-04-08T11:49:35.130358Z","shell.execute_reply":"2025-04-08T11:49:38.484984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = T.device('cuda' if T.cuda.is_available() else 'cpu')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:38.487465Z","iopub.execute_input":"2025-04-08T11:49:38.487883Z","iopub.status.idle":"2025-04-08T11:49:38.540323Z","shell.execute_reply.started":"2025-04-08T11:49:38.487861Z","shell.execute_reply":"2025-04-08T11:49:38.539379Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 读取文件\ntrain_data = pd.read_csv(\"/kaggle/input/dog-breed-identification/labels.csv\")\n# Train data shape\nprint(f\"Train dataset shape: {train_data.shape}\")\n# Sample of the train_data DataFrame\ntrain_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:38.542054Z","iopub.execute_input":"2025-04-08T11:49:38.542433Z","iopub.status.idle":"2025-04-08T11:49:38.614960Z","shell.execute_reply.started":"2025-04-08T11:49:38.542393Z","shell.execute_reply":"2025-04-08T11:49:38.614085Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"breed_classes = train_data.breed.value_counts().reset_index()\nplt.figure(figsize=(20,8))\nsns.barplot(breed_classes, x='breed', y='count', palette=\"flare\")\nplt.xticks(rotation=90)\nplt.title(\"Distribution of the breed classes\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:38.616024Z","iopub.execute_input":"2025-04-08T11:49:38.616310Z","iopub.status.idle":"2025-04-08T11:49:39.785728Z","shell.execute_reply.started":"2025-04-08T11:49:38.616290Z","shell.execute_reply":"2025-04-08T11:49:39.784827Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"breed_classes['count'].describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.786435Z","iopub.execute_input":"2025-04-08T11:49:39.786686Z","iopub.status.idle":"2025-04-08T11:49:39.796231Z","shell.execute_reply.started":"2025-04-08T11:49:39.786662Z","shell.execute_reply":"2025-04-08T11:49:39.795538Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"breed_classes['breed'].nunique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.797169Z","iopub.execute_input":"2025-04-08T11:49:39.797389Z","iopub.status.idle":"2025-04-08T11:49:39.814066Z","shell.execute_reply.started":"2025-04-08T11:49:39.797370Z","shell.execute_reply":"2025-04-08T11:49:39.813317Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"le = LabelEncoder()\ntrain_data.loc[:,'breed'] = le.fit_transform(train_data.loc[:,'breed']) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.814899Z","iopub.execute_input":"2025-04-08T11:49:39.815165Z","iopub.status.idle":"2025-04-08T11:49:39.830808Z","shell.execute_reply.started":"2025-04-08T11:49:39.815143Z","shell.execute_reply":"2025-04-08T11:49:39.830000Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.833069Z","iopub.execute_input":"2025-04-08T11:49:39.833269Z","iopub.status.idle":"2025-04-08T11:49:39.851460Z","shell.execute_reply.started":"2025-04-08T11:49:39.833251Z","shell.execute_reply":"2025-04-08T11:49:39.850749Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Dog_Breed_Dataset(Dataset):\n    \n    def __init__(self, df: pd.DataFrame, img_base_path: str, split: str, transforms = None):        \n        self.df = df\n        self.img_base_path = img_base_path\n        self.split = split\n        self.transforms = transforms\n        \n    def __getitem__(self, index):\n        # 图片路径\n        img_path = os.path.join(self.img_base_path + self.df.loc[index,'id'] + '.jpg')\n        # 读取图片\n        img = Image.open(img_path)        \n      \n        if self.transforms:\n            img = self.transforms(img)\n        \n        if self.split != 'test':\n            y = self.df.loc[index, 'breed']                     \n            return img, y\n        else:\n            img_id = self.df.loc[index, 'id']\n            return img_id, img\n    \n    def __len__(self):\n        return len(self.df)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.853151Z","iopub.execute_input":"2025-04-08T11:49:39.853357Z","iopub.status.idle":"2025-04-08T11:49:39.866781Z","shell.execute_reply.started":"2025-04-08T11:49:39.853339Z","shell.execute_reply":"2025-04-08T11:49:39.865939Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transforms = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.RandomHorizontalFlip(p=0.2),\n    transforms.RandomVerticalFlip(p=0.2),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\ntest_transforms = transforms.Compose([\n    transforms.Resize((224,224)),    \n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.867460Z","iopub.execute_input":"2025-04-08T11:49:39.867702Z","iopub.status.idle":"2025-04-08T11:49:39.881257Z","shell.execute_reply.started":"2025-04-08T11:49:39.867682Z","shell.execute_reply":"2025-04-08T11:49:39.880645Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train, val = train_test_split(train_data, test_size=0.2, random_state=42, stratify=train_data['breed'])\n\ntrain = train.reset_index(drop=True)\nval = val.reset_index(drop=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.882025Z","iopub.execute_input":"2025-04-08T11:49:39.882330Z","iopub.status.idle":"2025-04-08T11:49:39.909295Z","shell.execute_reply.started":"2025-04-08T11:49:39.882300Z","shell.execute_reply":"2025-04-08T11:49:39.908686Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = Dog_Breed_Dataset(\n    df=train,\n    img_base_path='/kaggle/input/dog-breed-identification/train/',\n    split='train',\n    transforms=train_transforms\n)\nvalidation_dataset = Dog_Breed_Dataset(\n    df=val,\n    img_base_path='/kaggle/input/dog-breed-identification/train/',\n    split='val',\n    transforms=test_transforms\n)\n\ntrain_dl = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=4)\nvalidation_dl = DataLoader(validation_dataset, batch_size=64, shuffle=False, num_workers=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.910114Z","iopub.execute_input":"2025-04-08T11:49:39.910376Z","iopub.status.idle":"2025-04-08T11:49:39.915425Z","shell.execute_reply.started":"2025-04-08T11:49:39.910346Z","shell.execute_reply":"2025-04-08T11:49:39.914589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Train data length: {len(train_dl.dataset)}, Validation data length: {len(validation_dl.dataset)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.916241Z","iopub.execute_input":"2025-04-08T11:49:39.916502Z","iopub.status.idle":"2025-04-08T11:49:39.934655Z","shell.execute_reply.started":"2025-04-08T11:49:39.916471Z","shell.execute_reply":"2025-04-08T11:49:39.933801Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch as T\n\n\ndef train_model(train_dl, val_dl, model, epochs=30):\n    train_acc_history = []\n    val_acc_history = []\n    train_loss_history = []\n    \n    val_loss_history = []\n    train_recall_history = []\n    val_recall_history = []\n   \n    best_val_loss = 1_000_000.0\n\n    device = next(model.parameters()).device\n\n    def evaluate(model, data_loader):\n        correct_pred = 0\n        total_loss = 0\n        true_positives = 0\n        actual_positives = 0\n        model.eval()\n        with T.no_grad():\n            for x, y in data_loader:\n                # Convert data to Tensor\n                x = x.clone().detach().to(device)\n                y = y.clone().detach().long().to(device)\n                # 预测\n                preds = model(x)\n                # 计算损失\n                loss = model.criterion(preds, y)\n                total_loss += loss.item()\n                # 计算正确的预测\n                preds = T.argmax(preds, dim=1)\n                correct_pred += (preds.long().unsqueeze(1) == y.unsqueeze(1)).sum().item()\n                # Calculate true positives and actual positives for recall\n                true_positives += ((preds == 1) & (y == 1)).sum().item()\n                actual_positives += (y == 1).sum().item()\n        accuracy = correct_pred / len(data_loader.dataset)\n        average_loss = total_loss / len(data_loader)\n        recall = true_positives / actual_positives if actual_positives > 0 else 0\n        return accuracy, average_loss, recall\n\n    for epoch in range(epochs):\n        print(\"=\" * 20, \"Epoch: \", str(epoch), \"=\" * 20)\n\n        train_correct_pred = 0\n        train_loss = 0\n        train_true_positives = 0\n        train_actual_positives = 0\n\n        # Set to training mode\n        model.train()\n        for x, y in train_dl:\n            # Convert data to Tensor\n            x = x.clone().detach().to(device).requires_grad_(True)\n            y = y.clone().detach().long().to(device)\n            # Reset gradients\n            model.optim.zero_grad()\n            # Predict\n            preds = model(x)\n            # Compute the loss\n            loss = model.criterion(preds, y)\n            # Compute the gradients\n            loss.backward()\n            # Update weights\n            model.optim.step()\n            # Count the correct predictions\n            preds = T.argmax(preds, dim=1)\n            train_correct_pred += (preds.long().unsqueeze(1) == y.unsqueeze(1)).sum().item()\n            train_loss += loss.item()\n            # Calculate true positives and actual positives for recall\n            train_true_positives += ((preds == 1) & (y == 1)).sum().item()\n            train_actual_positives += (y == 1).sum().item()\n\n        train_acc = train_correct_pred / len(train_dl.dataset)\n        train_loss /= len(train_dl)\n        train_recall = train_true_positives / train_actual_positives if train_actual_positives > 0 else 0\n\n        train_acc_history.append(train_acc)\n        train_loss_history.append(train_loss)\n        train_recall_history.append(train_recall)\n\n        val_acc, val_loss, val_recall = evaluate(model, val_dl)\n        model.scheduler.step()\n\n        val_acc_history.append(val_acc)\n        val_loss_history.append(val_loss)\n        val_recall_history.append(val_recall)\n\n        print(f\"Train Acc: {train_acc:.4f}, Train Loss: {train_loss:.4f}, Train Recall: {train_recall:.4f}, Val Acc: {val_acc:.4f}, Val Loss: {val_loss:.4f}, Val Recall: {val_recall:.4f}\")\n\n    return train_acc_history, val_acc_history, train_loss_history, val_loss_history, train_recall_history, val_recall_history, model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.935690Z","iopub.execute_input":"2025-04-08T11:49:39.936006Z","iopub.status.idle":"2025-04-08T11:49:39.953023Z","shell.execute_reply.started":"2025-04-08T11:49:39.935971Z","shell.execute_reply":"2025-04-08T11:49:39.952301Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.models as models\n\ninception = models.inception_v3(weights=None)  \n\n\nmodel_path = '/kaggle/input/inception/pytorch/default/1/inception_v3_google-0cc3c7bd.pth'  \nif not os.path.exists(model_path):\n    raise FileNotFoundError(f\"Model file not found at {model_path}\")\ninception.load_state_dict(torch.load(model_path))\n\ninception_model = nn.Sequential(\n    inception.Conv2d_1a_3x3,\n    inception.Conv2d_2a_3x3,\n    inception.Conv2d_2b_3x3,\n    inception.maxpool1,\n    inception.Conv2d_3b_1x1,\n    inception.Conv2d_4a_3x3,\n    inception.maxpool2,\n    inception.Mixed_5b,\n    inception.Mixed_5c,\n    inception.Mixed_5d,\n    inception.Mixed_6a,\n    inception.Mixed_6b,\n    inception.Mixed_6c,\n    inception.Mixed_6d,\n    inception.Mixed_6e,\n    inception.Mixed_7a,\n    inception.Mixed_7b,\n    inception.Mixed_7c,\n    inception.avgpool\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:39.953678Z","iopub.execute_input":"2025-04-08T11:49:39.953889Z","iopub.status.idle":"2025-04-08T11:49:41.676764Z","shell.execute_reply.started":"2025-04-08T11:49:39.953867Z","shell.execute_reply":"2025-04-08T11:49:41.676036Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_path = '/kaggle/input/resnet/pytorch/default/1/resnet50-0676ba61.pth'\n\n# 验证文件存在性\nif not os.path.exists(model_path):\n    raise FileNotFoundError(f\"Model file not found at {model_path}\")\n\n# 加载本地模型\nresnet50 = models.resnet50(weights=None)\nresnet50.load_state_dict(torch.load(model_path))\nresnet50_model = nn.Sequential(\n    resnet50.conv1,\n    resnet50.bn1,\n    resnet50.relu,\n    resnet50.maxpool,\n    resnet50.layer1,\n    resnet50.layer2,\n    resnet50.layer3,\n    resnet50.layer4,\n    resnet50.avgpool\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:41.677611Z","iopub.execute_input":"2025-04-08T11:49:41.677914Z","iopub.status.idle":"2025-04-08T11:49:42.922268Z","shell.execute_reply.started":"2025-04-08T11:49:41.677884Z","shell.execute_reply":"2025-04-08T11:49:42.921587Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Freeze parameters of pretrained models\nfor param in resnet50_model.parameters():    \n    param.requires_grad = False\n    \nfor param in inception_model.parameters():    \n    param.requires_grad = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:42.923063Z","iopub.execute_input":"2025-04-08T11:49:42.923358Z","iopub.status.idle":"2025-04-08T11:49:42.928301Z","shell.execute_reply.started":"2025-04-08T11:49:42.923330Z","shell.execute_reply":"2025-04-08T11:49:42.927456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, inception_model, resnet50_model):\n        super(Model, self).__init__()\n\n        self.inception_model = inception_model\n        self.resnet50_model = resnet50_model\n\n        self.output = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(4096, 120)\n        )\n\n        self.to('cuda' if T.cuda.is_available() else 'cpu')\n        # Optimizer\n        self.optim = T.optim.Adam(self.output.parameters(), lr=0.001)\n        # Loss\n        self.criterion = T.nn.CrossEntropyLoss()\n        # Scheduler\n        self.scheduler = T.optim.lr_scheduler.StepLR(self.optim, step_size=7, gamma=0.1)\n\n    def forward(self, x):\n        X1 = self.inception_model(x)\n        X2 = self.resnet50_model(x)\n        X1 = X1.view(X1.size(0), -1)\n        X2 = X2.view(X2.size(0), -1)\n\n        X = T.cat([X1, X2], dim=1)\n\n        P = self.output(X)\n\n        return P\n\n    def get_weights(self):\n        return self.output.state_dict()\n\n    def load_weights(self, weights):\n        self.output.load_state_dict(weights)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:42.929093Z","iopub.execute_input":"2025-04-08T11:49:42.929307Z","iopub.status.idle":"2025-04-08T11:49:42.944949Z","shell.execute_reply.started":"2025-04-08T11:49:42.929285Z","shell.execute_reply":"2025-04-08T11:49:42.944319Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = Model(inception_model, resnet50_model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:42.945755Z","iopub.execute_input":"2025-04-08T11:49:42.946008Z","iopub.status.idle":"2025-04-08T11:49:43.217277Z","shell.execute_reply.started":"2025-04-08T11:49:42.945977Z","shell.execute_reply":"2025-04-08T11:49:43.216478Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_acc_history, val_acc_history, train_loss_history, val_loss_history, train_recall_history, val_recall_history, model = train_model(train_dl, validation_dl, model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T11:49:43.218039Z","iopub.execute_input":"2025-04-08T11:49:43.218263Z","iopub.status.idle":"2025-04-08T12:24:03.439670Z","shell.execute_reply.started":"2025-04-08T11:49:43.218243Z","shell.execute_reply":"2025-04-08T12:24:03.438699Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 绘制准确率曲线\nplt.figure(figsize=(12, 4))\n\nplt.subplot(1, 3, 1)\nplt.plot(range(len(train_acc_history)), train_acc_history, label=\"Training accuracy\")\nplt.plot(range(len(val_acc_history)), val_acc_history, label=\"Validation accuracy\")\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.title('Accuracy Over Epochs')\nplt.legend()\nplt.grid(True)\n\n# 绘制损失曲线\nplt.subplot(1, 3, 2)\nplt.plot(range(len(train_loss_history)), train_loss_history, label=\"Training Loss\")\nplt.plot(range(len(val_loss_history)), val_loss_history, label=\"Validation Loss\")\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.title('Loss Over Epochs')\nplt.legend()\nplt.grid(True)\n\nplt.subplot(1, 3, 3)\nplt.plot(range(len(train_recall_history)), train_recall_history, label=\"Training Recall\")\nplt.plot(range(len(val_recall_history)), val_recall_history, label=\"Validation Recall\")\nplt.xlabel('Epoch')\nplt.ylabel('Recall')\nplt.title('Recall Over Epochs')\nplt.legend()\nplt.grid(True)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:03.441180Z","iopub.execute_input":"2025-04-08T12:24:03.441456Z","iopub.status.idle":"2025-04-08T12:24:04.007023Z","shell.execute_reply.started":"2025-04-08T12:24:03.441429Z","shell.execute_reply":"2025-04-08T12:24:04.006184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#test_data = pd.DataFrame([])\n# 获取测试目录下的所有文件名\ntest_dir = '/kaggle/input/dog-breed-identification/test/'\nfilenames = os.listdir(test_dir)\n\n# 创建包含测试数据的 DataFrame\ntest_data = pd.DataFrame({'id': filenames})\n\n# 去除文件名中的 .jpg 后缀\ntest_data['id'] = test_data['id'].str.replace('.jpg', '', regex=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:04.007814Z","iopub.execute_input":"2025-04-08T12:24:04.008031Z","iopub.status.idle":"2025-04-08T12:24:04.026403Z","shell.execute_reply.started":"2025-04-08T12:24:04.008013Z","shell.execute_reply":"2025-04-08T12:24:04.025587Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Dataset shape\nprint(f\"Test dataset shape: {test_data.shape}\")\n# Sample of the train_data DataFrame\ntest_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:04.027312Z","iopub.execute_input":"2025-04-08T12:24:04.027582Z","iopub.status.idle":"2025-04-08T12:24:04.036460Z","shell.execute_reply.started":"2025-04-08T12:24:04.027551Z","shell.execute_reply":"2025-04-08T12:24:04.035596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dataset = Dog_Breed_Dataset(\n    df=test_data,\n    img_base_path='/kaggle/input/dog-breed-identification/test/',\n    split='test',\n    transforms=test_transforms\n)\n\ntest_dl = DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:04.037446Z","iopub.execute_input":"2025-04-08T12:24:04.037686Z","iopub.status.idle":"2025-04-08T12:24:04.053468Z","shell.execute_reply.started":"2025-04-08T12:24:04.037667Z","shell.execute_reply":"2025-04-08T12:24:04.052839Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def test_model(test_dl, model):\n    all_ids = []\n    all_preds = []\n    device = next(model.parameters()).device\n    for ids, images in test_dl:\n        all_ids.extend(ids)\n        images = images.to(device)\n        preds = model(images)\n        prob_preds = T.nn.functional.softmax(preds, dim=1)\n        prob_preds = prob_preds.detach().cpu().numpy()\n        all_preds.extend(prob_preds)\n\n    result_df = pd.DataFrame(all_preds)\n    result_df.insert(0, 'id', all_ids)\n    return result_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:04.054239Z","iopub.execute_input":"2025-04-08T12:24:04.054445Z","iopub.status.idle":"2025-04-08T12:24:04.067538Z","shell.execute_reply.started":"2025-04-08T12:24:04.054419Z","shell.execute_reply":"2025-04-08T12:24:04.066852Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_preds = test_model(test_dl, model)\ntest_preds.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:04.070957Z","iopub.execute_input":"2025-04-08T12:24:04.071177Z","iopub.status.idle":"2025-04-08T12:24:37.158142Z","shell.execute_reply.started":"2025-04-08T12:24:04.071159Z","shell.execute_reply":"2025-04-08T12:24:37.157124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_preds.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:37.159291Z","iopub.execute_input":"2025-04-08T12:24:37.159549Z","iopub.status.idle":"2025-04-08T12:24:37.183747Z","shell.execute_reply.started":"2025-04-08T12:24:37.159501Z","shell.execute_reply":"2025-04-08T12:24:37.182953Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Set columns to breed names\nnum_classes = []\nfor num_class in test_preds.columns:\n    if num_class != 'id':  # 跳过id列\n        num_classes.append(num_class)\n\nnum_classes = np.array(num_classes)\nnum_classes = le.inverse_transform(num_classes)\ntest_preds.columns = ['id'] + list(num_classes)  # 将id列放在最前面","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:37.184578Z","iopub.execute_input":"2025-04-08T12:24:37.184872Z","iopub.status.idle":"2025-04-08T12:24:37.199874Z","shell.execute_reply.started":"2025-04-08T12:24:37.184850Z","shell.execute_reply":"2025-04-08T12:24:37.199012Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_preds.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:24:37.200824Z","iopub.execute_input":"2025-04-08T12:24:37.201151Z","iopub.status.idle":"2025-04-08T12:24:37.237438Z","shell.execute_reply.started":"2025-04-08T12:24:37.201122Z","shell.execute_reply":"2025-04-08T12:24:37.236680Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_preds.to_csv('submission.csv', index=None)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-08T12:26:57.576071Z","iopub.execute_input":"2025-04-08T12:26:57.576387Z","iopub.status.idle":"2025-04-08T12:26:58.928513Z","shell.execute_reply.started":"2025-04-08T12:26:57.576365Z","shell.execute_reply":"2025-04-08T12:26:58.927568Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}