{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":30747,"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","execution":{"iopub.status.busy":"2024-07-21T10:25:55.235396Z","iopub.execute_input":"2024-07-21T10:25:55.235752Z","iopub.status.idle":"2024-07-21T10:25:56.137231Z","shell.execute_reply.started":"2024-07-21T10:25:55.235724Z","shell.execute_reply":"2024-07-21T10:25:56.136314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ファイルの新設","metadata":{}},{"cell_type":"code","source":"!unzip /kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip\n!unzip /kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:25:56.139177Z","iopub.execute_input":"2024-07-21T10:25:56.139651Z","iopub.status.idle":"2024-07-21T10:26:14.107329Z","shell.execute_reply.started":"2024-07-21T10:25:56.139619Z","shell.execute_reply":"2024-07-21T10:26:14.106417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ライブラリのインポート","metadata":{}},{"cell_type":"code","source":"import os\nimport shutil\nfrom sklearn.model_selection import train_test_split\nfrom torchvision import datasets, transforms\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.utils.data as data\nimport torch.nn.functional as F\nfrom torchvision import models\nfrom torchvision.models import MobileNet_V2_Weights\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nfrom glob import glob\nfrom tqdm import tqdm\nimport copy\nimport csv\nimport re","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:14.108856Z","iopub.execute_input":"2024-07-21T10:26:14.109220Z","iopub.status.idle":"2024-07-21T10:26:19.463379Z","shell.execute_reply.started":"2024-07-21T10:26:14.109181Z","shell.execute_reply":"2024-07-21T10:26:19.462569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# リスト作成\nデータパスの構築． 検証用データと訓練用データを分類．","metadata":{}},{"cell_type":"code","source":"img = []\nlb = []\n\npath = \"/kaggle/working/train/\"\nfiles = glob(path + \"*.jpg\")\n\nfor file in files:\n    # 画像パス と ラベル\n    img.append(file)\n    if file.split('.')[-3].split('/')[-1] == \"cat\":\n        lb.append(0)\n    elif file.split('.')[-3].split('/')[-1] == \"dog\":\n        lb.append(1)\n\ntrain_data = img[:int(len(img)*0.8)], lb[:int(len(lb)*0.8)]\nval_data = img[int(len(img)*0.8):], lb[int(len(lb)*0.8):]","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:19.465962Z","iopub.execute_input":"2024-07-21T10:26:19.466750Z","iopub.status.idle":"2024-07-21T10:26:19.595891Z","shell.execute_reply.started":"2024-07-21T10:26:19.466716Z","shell.execute_reply":"2024-07-21T10:26:19.594992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 前処理\nサイズを同一にする． 色情報を標準化．","metadata":{}},{"cell_type":"code","source":"class ImageTransform:\n\n    def __init__(self, resize, mean, std):\n        self.data_transform = transforms.Compose(\n            [\n                transforms.Resize(resize),\n                transforms.CenterCrop(resize),\n                transforms.ToTensor(),\n                transforms.Normalize(mean, std),\n            ]\n        )\n\n    def __call__(self, img):\n        return self.data_transform(img)","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:19.596883Z","iopub.execute_input":"2024-07-21T10:26:19.598130Z","iopub.status.idle":"2024-07-21T10:26:19.612886Z","shell.execute_reply.started":"2024-07-21T10:26:19.598103Z","shell.execute_reply":"2024-07-21T10:26:19.611072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データセット\nセータセットを生成．画像のファイルとラベルのリストを受け取り枚処理をして返す．","metadata":{}},{"cell_type":"code","source":"class AnimalDataset(data.Dataset):\n\n    def __init__(self, file_list, label_list, transform=None):\n        self.file_list = file_list  # 画像ファイルパス\n        self.label_list = label_list  # ラベル\n        self.transform = transform  # 前処理のインスタンス\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def __getitem__(self, index):\n        img_path = self.file_list[index]\n        img = Image.open(img_path)\n        img_t = self.transform(img)\n        return img_t, int(self.label_list[index])","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:19.614391Z","iopub.execute_input":"2024-07-21T10:26:19.614750Z","iopub.status.idle":"2024-07-21T10:26:19.626524Z","shell.execute_reply.started":"2024-07-21T10:26:19.614716Z","shell.execute_reply":"2024-07-21T10:26:19.625660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"size = 224\nmean = (0.485, 0.456, 0.406)\nstd = (0.229, 0.224, 0.225)\n\ntrain_dataset = AnimalDataset(train_data[0], train_data[1], ImageTransform(size, mean, std))\nval_dataset = AnimalDataset(val_data[0], val_data[1], ImageTransform(size, mean, std))","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:19.627777Z","iopub.execute_input":"2024-07-21T10:26:19.628131Z","iopub.status.idle":"2024-07-21T10:26:19.635729Z","shell.execute_reply.started":"2024-07-21T10:26:19.628098Z","shell.execute_reply":"2024-07-21T10:26:19.634827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データローダ作成","metadata":{}},{"cell_type":"code","source":"batch_size = 32\n\ntrain_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_dataloader = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size,shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:19.636999Z","iopub.execute_input":"2024-07-21T10:26:19.637362Z","iopub.status.idle":"2024-07-21T10:26:19.645313Z","shell.execute_reply.started":"2024-07-21T10:26:19.637329Z","shell.execute_reply":"2024-07-21T10:26:19.644564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.mobilenet_v2(weights=MobileNet_V2_Weights.DEFAULT)\nmodel.classifier[1] = nn.Linear(in_features=1280, out_features=2)","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:19.646431Z","iopub.execute_input":"2024-07-21T10:26:19.646773Z","iopub.status.idle":"2024-07-21T10:26:20.281288Z","shell.execute_reply.started":"2024-07-21T10:26:19.646741Z","shell.execute_reply":"2024-07-21T10:26:20.280361Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:20.284054Z","iopub.execute_input":"2024-07-21T10:26:20.284375Z","iopub.status.idle":"2024-07-21T10:26:20.288915Z","shell.execute_reply.started":"2024-07-21T10:26:20.284350Z","shell.execute_reply":"2024-07-21T10:26:20.287807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習関数\nモデルを訓練する． 指定されたエポック数にわたって訓練と検証のフェーズを繰り返して損失と正解率を表示．","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\nend = False\n\ncriterion = torch.nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n\nepochs = 25\nbest_model_wts = copy.deepcopy(model.state_dict())\nbest_acc = 0.0  # 最良の精度を初期化\n\nfor epoch in range(epochs):\n    print(\"\")\n    print('Epoch {}/{}'.format(epoch+1, epochs))\n    print('-----------------')\n    \n    for phase in ['train','val']:\n        if phase == 'train':\n            model.train()\n        else:\n            model.eval()\n        \n        epoch_loss = 0.0\n        epoch_corrects = 0\n        \n        if (epoch == 0) and (phase == 'train'):\n            continue\n        \n        for inputs, labels in tqdm(dataloaders_dict[phase]):\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            \n            optimizer.zero_grad() \n            \n            with torch.set_grad_enabled(phase == 'train'):\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n                _, preds = torch.max(outputs, 1)\n                \n                if phase == 'train':\n                    loss.backward()\n                    optimizer.step()\n                \n                epoch_loss += loss.item() * inputs.size(0)\n                epoch_corrects += torch.sum(preds == labels.data)\n        \n        epoch_loss = epoch_loss / len(dataloaders_dict[phase].dataset)\n        epoch_acc = epoch_corrects.double(\n        ) / len(dataloaders_dict[phase].dataset)\n\n        print('{} Loss: {:.4f} Acc: {:.4f}'.format(\n                phase, epoch_loss, epoch_acc))\n        \n        if phase == 'val' and epoch_acc > best_acc:\n            best_acc = epoch_acc\n            best_model_wts = copy.deepcopy(model.state_dict())\n            \nmodel.load_state_dict(best_model_wts)\n\ntorch.save(model.state_dict(), \"/kaggle/working/best_model_weight.pth\")","metadata":{"execution":{"iopub.status.busy":"2024-07-21T10:26:20.290216Z","iopub.execute_input":"2024-07-21T10:26:20.290525Z","iopub.status.idle":"2024-07-21T11:32:33.220193Z","shell.execute_reply.started":"2024-07-21T10:26:20.290502Z","shell.execute_reply":"2024-07-21T11:32:33.219225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ソート関数\n昇順に従って並べ替える","metadata":{}},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:32:33.221469Z","iopub.execute_input":"2024-07-21T11:32:33.221765Z","iopub.status.idle":"2024-07-21T11:32:33.226612Z","shell.execute_reply.started":"2024-07-21T11:32:33.221741Z","shell.execute_reply":"2024-07-21T11:32:33.225708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder_path = \"/kaggle/working/test/\"\nfiles = sorted(glob(folder_path + \"*.jpg\"), key=natural_keys)\nlabel = [1] * len(files)","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:32:33.227724Z","iopub.execute_input":"2024-07-21T11:32:33.228095Z","iopub.status.idle":"2024-07-21T11:32:33.350358Z","shell.execute_reply.started":"2024-07-21T11:32:33.228050Z","shell.execute_reply":"2024-07-21T11:32:33.349620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = AnimalDataset(files, label, ImageTransform(size, mean, std))\ntest_dataloader = torch.utils.data.DataLoader(test_dataset, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:32:33.351378Z","iopub.execute_input":"2024-07-21T11:32:33.351703Z","iopub.status.idle":"2024-07-21T11:32:33.357107Z","shell.execute_reply.started":"2024-07-21T11:32:33.351674Z","shell.execute_reply":"2024-07-21T11:32:33.356207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 推論モード","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nmodel = models.mobilenet_v2(pretrained=False)\nmodel.classifier[1] = nn.Linear(model.classifier[1].in_features, 2)\nmodel.load_state_dict(torch.load(\"/kaggle/working/best_model_weight.pth\", map_location=device))\nmodel = model.to(device)\nmodel.eval()","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:32:33.358288Z","iopub.execute_input":"2024-07-21T11:32:33.358561Z","iopub.status.idle":"2024-07-21T11:32:33.526910Z","shell.execute_reply.started":"2024-07-21T11:32:33.358538Z","shell.execute_reply":"2024-07-21T11:32:33.526031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 推論　保存\nブロックは勾配を計算しない．メモリを消費を減らして推論する．結果を出力．","metadata":{}},{"cell_type":"code","source":"with open('/kaggle/working/submission.csv', 'w', newline='') as f:\n    writer = csv.writer(f)\n    writer.writerow(['id', 'label'])\n    \n    count = 1\n    for x, _ in test_dataloader:\n        with torch.no_grad():\n            x = x.to(device)\n            pred = model(x)\n            predicted = F.softmax(pred, dim=1)[:, 1].cpu().numpy()\n            \n            for p in predicted:\n                writer.writerow([count, float(p)])\n                count += 1","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:32:33.528093Z","iopub.execute_input":"2024-07-21T11:32:33.528391Z","iopub.status.idle":"2024-07-21T11:34:39.149838Z","shell.execute_reply.started":"2024-07-21T11:32:33.528367Z","shell.execute_reply":"2024-07-21T11:34:39.148849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_data = pd.read_csv('/kaggle/working/submission.csv')\ncheck_data","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:34:39.151318Z","iopub.execute_input":"2024-07-21T11:34:39.151667Z","iopub.status.idle":"2024-07-21T11:34:39.186131Z","shell.execute_reply.started":"2024-07-21T11:34:39.151635Z","shell.execute_reply":"2024-07-21T11:34:39.185296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_data.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-07-21T11:34:39.187209Z","iopub.execute_input":"2024-07-21T11:34:39.187494Z","iopub.status.idle":"2024-07-21T11:34:39.228840Z","shell.execute_reply.started":"2024-07-21T11:34:39.187470Z","shell.execute_reply":"2024-07-21T11:34:39.228146Z"},"trusted":true},"execution_count":null,"outputs":[]}]}