{"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":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport zipfile\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, f1_score, confusion_matrix, ConfusionMatrixDisplay\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nimport matplotlib.pyplot as plt\n\n# ===== 1. パラメータ =====\nBATCH_SIZE = 64\nEPOCHS = 6\nIMG_SIZE = 128\nLR = 0.001\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"✅ Using: {device}\")\n\n# ===== 2. zipファイルの解凍 =====\ninput_dir = \"/kaggle/input/dogs-vs-cats-redux-kernels-edition/\"\nwork_dir = \"/kaggle/working/\"\n\nwith zipfile.ZipFile(input_dir + \"train.zip\", \"r\") as zip_ref:\n    zip_ref.extractall(work_dir + \"train/\")\nwith zipfile.ZipFile(input_dir + \"test.zip\", \"r\") as zip_ref:\n    zip_ref.extractall(work_dir + \"test/\")\n\ntrain_dir = os.path.join(work_dir, \"train/train\")\ntest_dir = os.path.join(work_dir, \"test/test\")\n\n# ===== 3. データセット定義 =====\nclass CatsDogsDataset(Dataset):\n    def __init__(self, filepaths, labels=None, transform=None):\n        self.filepaths = filepaths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.filepaths)\n\n    def __getitem__(self, idx):\n        image = Image.open(self.filepaths[idx]).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        if self.labels is not None:\n            return image, self.labels[idx]\n        else:\n            return image\n\n# ===== 4. ファイルとラベルの準備（順序保証） =====\nfile_names = sorted(os.listdir(train_dir))  # sortで順序固定\ntrain_files = [os.path.join(train_dir, f) for f in file_names]\nlabels = [1 if 'dog' in f else 0 for f in file_names]\n\nX_train, X_val, y_train, y_val = train_test_split(train_files, labels, test_size=0.1, random_state=42)\n\n# ===== 5. Transform定義（Data Augmentation + Normalize） =====\ntrain_transform = transforms.Compose([\n    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomRotation(10),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406],\n                         [0.229, 0.224, 0.225])\n])\n\nval_transform = transforms.Compose([\n    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406],\n                         [0.229, 0.224, 0.225])\n])\n\n# ===== 6. DataLoader作成 =====\ntrain_dataset = CatsDogsDataset(X_train, y_train, transform=train_transform)\nval_dataset = CatsDogsDataset(X_val, y_val, transform=val_transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=BATCH_SIZE)\n\n# ===== 7. モデル構築（VGG11） =====\nfrom torchvision.models import vgg11, VGG11_Weights\nmodel = vgg11(weights=VGG11_Weights.IMAGENET1K_V1)\nmodel.classifier[6] = nn.Linear(model.classifier[6].in_features, 2)\nmodel = model.to(device)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=LR)\n\n# ===== 8. 学習ループ =====\nfor epoch in range(EPOCHS):\n    model.train()\n    running_loss = 0.0\n    for images, labels in train_loader:\n        images, labels = images.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n    print(f\"[Epoch {epoch+1}] Loss: {running_loss / len(train_loader):.4f}\")\nprint(\"✅ 学習完了\")\n\n# ===== 9. 検証精度評価 =====\nmodel.eval()\nall_preds, all_labels = [], []\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        preds = torch.argmax(outputs, dim=1)\n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\nacc = accuracy_score(all_labels, all_preds)\nf1 = f1_score(all_labels, all_preds)\nprint(f\"🔍 Val Accuracy: {acc:.4f} | F1 Score: {f1:.4f}\")\n\n# 混合行列表示\ncm = confusion_matrix(all_labels, all_preds)\ndisp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=[\"Cat\", \"Dog\"])\ndisp.plot(cmap=\"Blues\", values_format=\"d\")\nplt.title(\"Confusion Matrix (Validation)\")\nplt.show()\n\n# ===== 10. 推論用（テストセット） =====\ntest_images = [f for f in os.listdir(test_dir) if f.endswith(\".jpg\")]\ntest_images = sorted(test_images, key=lambda x: int(x.split('.')[0]))\ntest_paths = [os.path.join(test_dir, fname) for fname in test_images]\n\ntest_dataset = CatsDogsDataset(test_paths, transform=val_transform)\ntest_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE)\n\npredictions = []\nwith torch.no_grad():\n    for images in test_loader:\n        images = images.to(device)\n        outputs = model(images)\n        probs = torch.softmax(outputs, dim=1)[:, 1]  # 犬の確率\n        predictions.extend(probs.cpu().numpy())\n\n# ===== 11. 提出用CSV作成 =====\nsubmission = pd.DataFrame({\n    \"id\": [int(fname.split(\".\")[0]) for fname in test_images],\n    \"label\": predictions\n})\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv を保存しました\")\n\n# モデル保存\ntorch.save(model.state_dict(), \"model.pth\")\n\n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n# 予測\nfrom sklearn.metrics import accuracy_score, f1_score, confusion_matrix, ConfusionMatrixDisplay\nimport matplotlib.pyplot as plt\n\n# 予測と正解を蓄積\nall_preds = []\nall_labels = []\n\nmodel.eval()\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        preds = torch.argmax(outputs, dim=1)\n\n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\n# 精度・F1\nacc = accuracy_score(all_labels, all_preds)\nf1 = f1_score(all_labels, all_preds)\n\nprint(\"🔍 学習モデルの評価結果\")\nprint(f\"Accuracy: {acc:.4f}\")\nprint(f\"F1 Score: {f1:.4f}\")\n\n# 混合行列\ncm = confusion_matrix(all_labels, all_preds)\ndisp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=[\"Cat\", \"Dog\"])\nprint(\"\\n📊 混合行列:\")\ndisp.plot(cmap=\"Blues\", values_format=\"d\")\nplt.title(\"Confusion Matrix (Model)\")\nplt.show()\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-25T07:02:17.715055Z","iopub.execute_input":"2025-07-25T07:02:17.715393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}