{"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":"gpu","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"dockerImageVersionId":30733,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"#モジュールのインポート\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nfrom PIL import Image\nimport os\nimport random\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.datasets as datasets\nfrom torchvision.models import resnet101\nfrom torchvision import transforms\n#ハイパーパラメータの調整\n#画像サイズはデータセットに合わせて32にした\nbatch_size = 64\nlearning_rate = 1e-4\nnum_epochs = 5\nimg_size = 32\n#乱数シードを固定し，同じ条件下での実験を再現可能にする\nrandom_seed = 42\nrandom.seed(random_seed)\nnp.random.seed(random_seed)\nos.environ[\"PYTHONHASHSEED\"] = str(random_seed)\ntorch.manual_seed(random_seed)\ntorch.cuda.manual_seed(random_seed)\ntorch.cuda.manual_seed_all(random_seed)\ntorch.backends.cudnn.deterministic = True\ntorch.backends.cudnn.benchmark = False\ntorch.use_deterministic_algorithms(False)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T10:57:25.569914Z","iopub.execute_input":"2024-06-28T10:57:25.570522Z","iopub.status.idle":"2024-06-28T10:57:30.752234Z","shell.execute_reply.started":"2024-06-28T10:57:25.570490Z","shell.execute_reply":"2024-06-28T10:57:30.751501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# csvファイルの読み込み\nsample = pd.read_csv('/kaggle/input/cifar-10/sampleSubmission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-06-28T10:57:34.202983Z","iopub.execute_input":"2024-06-28T10:57:34.203474Z","iopub.status.idle":"2024-06-28T10:57:34.335364Z","shell.execute_reply.started":"2024-06-28T10:57:34.203426Z","shell.execute_reply":"2024-06-28T10:57:34.334505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 画像のデータ拡張\n#画像のリサイズ，ランダム回転，反転の処理\ntrain_transforms = transforms.Compose(\n    [\n        transforms.Resize(img_size),\n        transforms.RandomRotation(20),\n        transforms.RandomHorizontalFlip(0.5),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ]\n)\ntest_transforms = transforms.Compose(\n    [\n        transforms.Resize(img_size),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ]\n)# Define transforms\ntrain_transforms = transforms.Compose(\n    [\n        transforms.Resize(img_size),\n        transforms.RandomRotation(20),\n        transforms.RandomHorizontalFlip(0.5),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ]\n)\ntest_transforms = transforms.Compose(\n    [\n        transforms.Resize(img_size),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ]\n)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T10:57:36.720589Z","iopub.execute_input":"2024-06-28T10:57:36.720963Z","iopub.status.idle":"2024-06-28T10:57:36.730266Z","shell.execute_reply.started":"2024-06-28T10:57:36.720933Z","shell.execute_reply":"2024-06-28T10:57:36.729267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#訓練，検証用，テストデータの読み込み\ntrain_dataset = datasets.CIFAR10(root='./data', train=True, transform=train_transforms, download=True)\nvalid_dataset = datasets.CIFAR10(root='./data', train=False, transform=test_transforms, download=True)\n\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=False)\nvalid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T10:57:39.954232Z","iopub.execute_input":"2024-06-28T10:57:39.955114Z","iopub.status.idle":"2024-06-28T10:57:47.373893Z","shell.execute_reply.started":"2024-06-28T10:57:39.955079Z","shell.execute_reply":"2024-06-28T10:57:47.372858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# モデル読み込み(この場合はResNet101(CNNベース))\nclass ResNet101(nn.Module):\n    def __init__(self, num_classes):\n        super(ResNet101, self).__init__()\n        self.model = resnet101(weights=\"DEFAULT\")\n        self.in_features = self.model.fc.in_features\n        self.model.fc = nn.Linear(self.in_features, num_classes)\n        \n    def forward(self, x):\n        x = self.model(x)\n        return x\n# 実行時にgpuを用いるようにする\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\n\n#モデル，オプティマイザ，損失関数の定義\nmodel = ResNet101(num_classes=10).to(device)\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\ncriterion = nn.CrossEntropyLoss().to(device)\nscheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.5)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T10:57:47.375543Z","iopub.execute_input":"2024-06-28T10:57:47.375830Z","iopub.status.idle":"2024-06-28T10:57:49.749666Z","shell.execute_reply.started":"2024-06-28T10:57:47.375805Z","shell.execute_reply":"2024-06-28T10:57:49.748671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 訓練時の処理\nbest_epoch = 0\nbest_acc = 0.0\nfor epoch in range(1, num_epochs + 1):\n    print(\"-\" * 40)\n    print(f\"Epoch: {epoch}\")\n    epoch_loss = 0.0\n    epoch_corrects = 0\n    model.train()\n    for batch_in, batch_out in tqdm(train_loader):\n        batch_in = batch_in.to(device)\n        batch_out = batch_out.to(device)\n\n        y_pred = model(batch_in)\n        preds = torch.argmax(y_pred, 1)\n        loss = criterion(y_pred, batch_out)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        epoch_loss += loss.item() * batch_in.size(0)\n        epoch_corrects += torch.sum(preds == batch_out.data)\n\n    epoch_loss = epoch_loss / len(train_loader.dataset)\n    epoch_acc = epoch_corrects / len(train_loader.dataset)\n\n    print(f\"Train loss: {epoch_loss:.4f}\")\n    print(f\"Train acc: {epoch_acc:.4f}\")\n\n#過学習を防ぐための検証用\n    with torch.no_grad():\n        epoch_loss = 0.0\n        epoch_corrects = 0\n        model.eval()\n        for batch_in, batch_out in tqdm(valid_loader):\n            batch_in = batch_in.to(device)\n            batch_out = batch_out.to(device)\n\n            y_pred = model(batch_in)\n            preds = torch.argmax(y_pred, 1)\n            loss = criterion(y_pred, batch_out)\n\n            epoch_loss += loss.item() * batch_in.size(0)\n            epoch_corrects += torch.sum(preds == batch_out.data)\n\n    epoch_loss = epoch_loss / len(valid_loader.dataset)\n    epoch_acc = epoch_corrects / len(valid_loader.dataset)\n    \n    scheduler.step()\n\n    print(f\"Valid loss: {epoch_loss:.4f}\")\n    print(f\"Valid acc: {epoch_acc:.4f}\")\n\n    if epoch_acc >= best_acc:\n        best_epoch = epoch\n        best_acc = epoch_acc\n        torch.save(model, \"./model.pt\")\n\n    print(f\"Best epoch: {best_epoch}\")\n    print(f\"Best acc: {best_acc:.4f}\")\n    print(\"-\" * 40)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T10:57:52.294985Z","iopub.execute_input":"2024-06-28T10:57:52.295815Z","iopub.status.idle":"2024-06-28T11:15:39.414263Z","shell.execute_reply.started":"2024-06-28T10:57:52.295780Z","shell.execute_reply":"2024-06-28T11:15:39.413352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ファイルの解凍\n!pip install py7zr\n\nimport py7zr\n\nwith py7zr.SevenZipFile('/kaggle/input/cifar-10/test.7z', mode='r') as z:\n    z.extractall('/kaggle/working/')","metadata":{"execution":{"iopub.status.busy":"2024-06-28T11:16:17.074186Z","iopub.execute_input":"2024-06-28T11:16:17.075069Z","iopub.status.idle":"2024-06-28T11:19:35.082802Z","shell.execute_reply.started":"2024-06-28T11:16:17.075034Z","shell.execute_reply":"2024-06-28T11:19:35.081725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#ファイル作成\ntest_filenames = [os.path.join('/kaggle/working/test', f) for f in os.listdir('/kaggle/working/test')]\ntest_filenames.sort(key=lambda x: int(x.split('/')[-1].split('.')[0]))","metadata":{"execution":{"iopub.status.busy":"2024-06-28T11:19:51.610142Z","iopub.execute_input":"2024-06-28T11:19:51.610528Z","iopub.status.idle":"2024-06-28T11:19:52.615932Z","shell.execute_reply.started":"2024-06-28T11:19:51.610498Z","shell.execute_reply":"2024-06-28T11:19:52.615154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#データセットの定義\nclass CIFAR10(Dataset):\n    def __init__(self, filenames, transforms):\n        self.filenames = filenames\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.filenames)\n    \n    def __getitem__(self, idx):\n        img = Image.open(self.filenames[idx])\n        transformed_img = self.transforms(img)\n        return transformed_img\n#テストデータの処理\ntest_dataset = CIFAR10(test_filenames, test_transforms)\n\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T11:20:01.598088Z","iopub.execute_input":"2024-06-28T11:20:01.598910Z","iopub.status.idle":"2024-06-28T11:20:01.605436Z","shell.execute_reply.started":"2024-06-28T11:20:01.598874Z","shell.execute_reply":"2024-06-28T11:20:01.604479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#CIFAR10のクラスの定義\nclasses = ('airplane', \n           'automobile', \n           'bird',\n           'cat',\n           'deer',\n           'dog', \n           'frog', \n           'horse', \n           'ship',\n           'truck')","metadata":{"execution":{"iopub.status.busy":"2024-06-28T11:20:05.150552Z","iopub.execute_input":"2024-06-28T11:20:05.150921Z","iopub.status.idle":"2024-06-28T11:20:05.155843Z","shell.execute_reply.started":"2024-06-28T11:20:05.150891Z","shell.execute_reply":"2024-06-28T11:20:05.154816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 一番精度がよかったエポックのモデルを呼び出す\nmodel = torch.load('./model.pt').to(device)\nresult = []\n#テストデータなので，no_gradで処理(重みを変えない)\nwith torch.no_grad():\n    model.eval()\n    for batch_in in tqdm(test_loader):\n        batch_in = batch_in.to(device)\n        \n        y_pred = model(batch_in)\n        preds = torch.argmax(y_pred, 1)\n        preds = preds.cpu().numpy()\n        result.extend([classes[i] for i in preds])\n\nsample['label'] = result\nsample.to_csv('./predict.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T11:20:12.238636Z","iopub.execute_input":"2024-06-28T11:20:12.239240Z","iopub.status.idle":"2024-06-28T11:23:59.757914Z","shell.execute_reply.started":"2024-06-28T11:20:12.239209Z","shell.execute_reply":"2024-06-28T11:23:59.757122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#データを削除(不要のため)\nimport shutil\n\nshutil.rmtree('/kaggle/working/data')\nshutil.rmtree('/kaggle/working/test')","metadata":{"execution":{"iopub.status.busy":"2024-06-28T11:24:02.503802Z","iopub.execute_input":"2024-06-28T11:24:02.504137Z","iopub.status.idle":"2024-06-28T11:24:15.904580Z","shell.execute_reply.started":"2024-06-28T11:24:02.504110Z","shell.execute_reply":"2024-06-28T11:24:15.903558Z"},"trusted":true},"execution_count":null,"outputs":[]}]}