{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.11"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false},"papermill":{"default_parameters":{},"duration":3592.575496,"end_time":"2025-07-11T08:46:27.646643","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-07-11T07:46:35.071147","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"d6e34ce7","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":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2025-07-11T07:46:40.167411Z","iopub.status.busy":"2025-07-11T07:46:40.167097Z","iopub.status.idle":"2025-07-11T07:46:42.026299Z","shell.execute_reply":"2025-07-11T07:46:42.025114Z"},"papermill":{"duration":1.866686,"end_time":"2025-07-11T07:46:42.027875","exception":false,"start_time":"2025-07-11T07:46:40.161189","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"ad0f8705","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\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\n\n# ===== 1. 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/\")\n\nwith zipfile.ZipFile(input_dir + \"test.zip\", \"r\") as zip_ref:\n    zip_ref.extractall(work_dir + \"test/\")\n","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:46:42.036907Z","iopub.status.busy":"2025-07-11T07:46:42.036509Z","iopub.status.idle":"2025-07-11T07:47:10.275731Z","shell.execute_reply":"2025-07-11T07:47:10.274864Z"},"papermill":{"duration":28.245667,"end_time":"2025-07-11T07:47:10.277486","exception":false,"start_time":"2025-07-11T07:46:42.031819","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"10ba37a3","cell_type":"code","source":"train_root = os.path.join(work_dir, \"train\")\ntest_root = os.path.join(work_dir, \"test\")\n\nprint(\"📁 train フォルダの内容（上位10件）:\")\nprint(os.listdir(train_root)[:10])  # train直下にtrainフォルダがあるか確認\n\nprint(\"\\n📁 train/train フォルダの内容（上位10件）:\")\nprint(os.listdir(os.path.join(train_root, \"train\"))[:10])\n\nprint(\"\\n📁 test/test フォルダの内容（上位10件）:\")\nprint(os.listdir(os.path.join(test_root, \"test\"))[:10])","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:10.287130Z","iopub.status.busy":"2025-07-11T07:47:10.286683Z","iopub.status.idle":"2025-07-11T07:47:10.313878Z","shell.execute_reply":"2025-07-11T07:47:10.312722Z"},"papermill":{"duration":0.033602,"end_time":"2025-07-11T07:47:10.315430","exception":false,"start_time":"2025-07-11T07:47:10.281828","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"4f0a6508","cell_type":"code","source":"# ===== 3. パラメータ =====\nBATCH_SIZE = 64\nEPOCHS = 3\nIMG_SIZE = 128\nLR = 0.001\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"\\n✅ Using:\", device)","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:10.324408Z","iopub.status.busy":"2025-07-11T07:47:10.324055Z","iopub.status.idle":"2025-07-11T07:47:10.333732Z","shell.execute_reply":"2025-07-11T07:47:10.332332Z"},"papermill":{"duration":0.01601,"end_time":"2025-07-11T07:47:10.335456","exception":false,"start_time":"2025-07-11T07:47:10.319446","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"4c3dc5f7","cell_type":"code","source":"# ===== 4. Dataset定義 =====\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","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:10.344539Z","iopub.status.busy":"2025-07-11T07:47:10.344198Z","iopub.status.idle":"2025-07-11T07:47:10.350267Z","shell.execute_reply":"2025-07-11T07:47:10.349374Z"},"papermill":{"duration":0.012275,"end_time":"2025-07-11T07:47:10.351888","exception":false,"start_time":"2025-07-11T07:47:10.339613","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"0b86cf7a","cell_type":"code","source":"# ===== 5. ファイルとラベル準備 =====\ntrain_dir = os.path.join(train_root, \"train\")\ntest_dir = os.path.join(test_root, \"test\")\n\ntrain_files = [os.path.join(train_dir, f) for f in os.listdir(train_dir)]\nlabels = [1 if 'dog' in f else 0 for f in os.listdir(train_dir)]\n\nX_train, X_val, y_train, y_val = train_test_split(train_files, labels, test_size=0.1, random_state=42)","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:10.360838Z","iopub.status.busy":"2025-07-11T07:47:10.360513Z","iopub.status.idle":"2025-07-11T07:47:10.425042Z","shell.execute_reply":"2025-07-11T07:47:10.424278Z"},"papermill":{"duration":0.070705,"end_time":"2025-07-11T07:47:10.426568","exception":false,"start_time":"2025-07-11T07:47:10.355863","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"691d52df","cell_type":"code","source":"# ===== 6. データ変換とDataLoader =====\ntransform = transforms.Compose([\n    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n    transforms.ToTensor(),\n])\n\ntrain_dataset = CatsDogsDataset(X_train, y_train, transform)\nval_dataset = CatsDogsDataset(X_val, y_val, transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=BATCH_SIZE)","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:10.435490Z","iopub.status.busy":"2025-07-11T07:47:10.435138Z","iopub.status.idle":"2025-07-11T07:47:10.441276Z","shell.execute_reply":"2025-07-11T07:47:10.440299Z"},"papermill":{"duration":0.012201,"end_time":"2025-07-11T07:47:10.442798","exception":false,"start_time":"2025-07-11T07:47:10.430597","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"924a2db1","cell_type":"code","source":"# ===== 7. モデル準備（ResNet18） =====\nmodel = models.resnet18(pretrained=True)\nmodel.fc = nn.Linear(model.fc.in_features, 2)\nmodel = model.to(device)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=LR)","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:10.451881Z","iopub.status.busy":"2025-07-11T07:47:10.451554Z","iopub.status.idle":"2025-07-11T07:47:11.084022Z","shell.execute_reply":"2025-07-11T07:47:11.083130Z"},"papermill":{"duration":0.638966,"end_time":"2025-07-11T07:47:11.085761","exception":false,"start_time":"2025-07-11T07:47:10.446795","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"b94eb067","cell_type":"code","source":"# ===== 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(\"train finish\")","metadata":{"execution":{"iopub.execute_input":"2025-07-11T07:47:11.097932Z","iopub.status.busy":"2025-07-11T07:47:11.096929Z","iopub.status.idle":"2025-07-11T08:40:12.445067Z","shell.execute_reply":"2025-07-11T08:40:12.443853Z"},"papermill":{"duration":3181.360279,"end_time":"2025-07-11T08:40:12.451956","exception":false,"start_time":"2025-07-11T07:47:11.091677","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"9a2441d5","cell_type":"code","source":"# ===== 9. テストデータ読み込みと予測 =====\nmodel.eval()\ntest_images = sorted(os.listdir(test_dir), 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=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())","metadata":{"execution":{"iopub.execute_input":"2025-07-11T08:40:12.462413Z","iopub.status.busy":"2025-07-11T08:40:12.462010Z","iopub.status.idle":"2025-07-11T08:43:38.594141Z","shell.execute_reply":"2025-07-11T08:43:38.593252Z"},"papermill":{"duration":206.139715,"end_time":"2025-07-11T08:43:38.596089","exception":false,"start_time":"2025-07-11T08:40:12.456374","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"2ed8ec66","cell_type":"code","source":"# ===== 10. 提出用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 を作成しました\")","metadata":{"execution":{"iopub.execute_input":"2025-07-11T08:43:38.607059Z","iopub.status.busy":"2025-07-11T08:43:38.606246Z","iopub.status.idle":"2025-07-11T08:43:38.677018Z","shell.execute_reply":"2025-07-11T08:43:38.676181Z"},"papermill":{"duration":0.077756,"end_time":"2025-07-11T08:43:38.678663","exception":false,"start_time":"2025-07-11T08:43:38.600907","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"e7e5a074","cell_type":"code","source":"from sklearn.metrics import accuracy_score, f1_score\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(f\"Val Accuracy: {acc:.4f} | F1 Score: {f1:.4f}\")\n","metadata":{"execution":{"iopub.execute_input":"2025-07-11T08:43:38.688828Z","iopub.status.busy":"2025-07-11T08:43:38.688526Z","iopub.status.idle":"2025-07-11T08:44:21.033379Z","shell.execute_reply":"2025-07-11T08:44:21.032272Z"},"papermill":{"duration":42.358226,"end_time":"2025-07-11T08:44:21.041470","exception":false,"start_time":"2025-07-11T08:43:38.683244","status":"completed"},"tags":[]},"outputs":[],"execution_count":null},{"id":"1b54c617","cell_type":"code","source":"# PyTorchモデルの保存\ntorch.save(model.state_dict(), \"model.pth\")","metadata":{"execution":{"iopub.execute_input":"2025-07-11T08:44:21.051990Z","iopub.status.busy":"2025-07-11T08:44:21.051211Z","iopub.status.idle":"2025-07-11T08:44:21.127975Z","shell.execute_reply":"2025-07-11T08:44:21.127212Z"},"papermill":{"duration":0.083844,"end_time":"2025-07-11T08:44:21.129807","exception":false,"start_time":"2025-07-11T08:44:21.045963","status":"completed"},"tags":[]},"outputs":[],"execution_count":null}]}