{"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":29193,"databundleVersionId":2318453,"sourceType":"competition"}],"dockerImageVersionId":30733,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install d2l","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:35:43.696851Z","iopub.execute_input":"2024-07-03T04:35:43.697595Z","iopub.status.idle":"2024-07-03T04:36:35.141743Z","shell.execute_reply.started":"2024-07-03T04:35:43.697555Z","shell.execute_reply":"2024-07-03T04:36:35.140793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import d2l.torch as d2l\nimport numpy as np\nimport pandas as pd\nimport random\nimport time\nimport torch\n\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\nfrom torch import nn\nfrom torch.utils.data import DataLoader\nfrom torch.utils.data import Dataset\nfrom torchvision import models\nfrom torchvision.transforms import v2\n\nTEST_SIZE = 0.1\nBATCH_SIZE = 128\nLR = 1e-4\nL2 = 1e-3\nEPOCHS = 50","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:35.143644Z","iopub.execute_input":"2024-07-03T04:36:35.143956Z","iopub.status.idle":"2024-07-03T04:36:40.836777Z","shell.execute_reply.started":"2024-07-03T04:36:35.143930Z","shell.execute_reply":"2024-07-03T04:36:40.836006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LeaveDataset(Dataset):\n    def __init__(self, x, y, train=True):\n        self.x = x\n        self.y = y\n        self.train = train\n        self.train_trans = v2.Compose([\n            v2.RandomHorizontalFlip(),\n            v2.RandomVerticalFlip(),\n            v2.RandomRotation(180, fill=(255,255,255)),\n            v2.ColorJitter(0.5),\n            v2.Resize((224, 224)),\n            v2.PILToTensor(),\n            v2.ToDtype(torch.float32, True),\n            v2.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])\n        self.other_trans = v2.Compose([\n            v2.Resize((224, 224)),\n            v2.PILToTensor(),\n            v2.ToDtype(torch.float32, True),\n            v2.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])\n    def __getitem__(self, index):\n        x = self.x[index]\n        y = self.y[index]\n        \n        x = Image.open('/kaggle/input/classify-leaves/' + x)\n        if self.train:\n            x = self.train_trans(x)\n        else:\n            x = self.other_trans(x)\n        \n        return x, y\n    def __len__(self):\n        return len(self.x)","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:40.837930Z","iopub.execute_input":"2024-07-03T04:36:40.838359Z","iopub.status.idle":"2024-07-03T04:36:40.848299Z","shell.execute_reply.started":"2024-07-03T04:36:40.838332Z","shell.execute_reply":"2024-07-03T04:36:40.847413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_train_data():\n    data = pd.read_csv('/kaggle/input/classify-leaves/train.csv')\n    \n    x, y = data['image'], data['label']\n    print(f'x={len(x)}, y={len(y)}')\n    \n    le = LabelEncoder()\n    y = le.fit_transform(y)\n    \n    train_x, valid_x, train_y, valid_y = train_test_split(\n        x, y, test_size=TEST_SIZE, random_state=66, shuffle=True, stratify=y)\n    print(f'train={len(train_x)}, valid={len(valid_x)}')\n    \n    train_ds, valid_ds = LeaveDataset(train_x.values, train_y), LeaveDataset(valid_x.values, valid_y, False)\n    print(f'train={len(train_ds)}, valid={len(valid_ds)}')\n    \n    train_dl, valid_dl = DataLoader(train_ds, BATCH_SIZE, shuffle=False, num_workers=3, persistent_workers=True), DataLoader(valid_ds, BATCH_SIZE, shuffle=False, num_workers=3, persistent_workers=True)\n    print(f'train={len(train_dl)}, valid={len(valid_dl)}')\n    \n    return train_dl, valid_dl, le","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:40.851092Z","iopub.execute_input":"2024-07-03T04:36:40.851490Z","iopub.status.idle":"2024-07-03T04:36:40.891370Z","shell.execute_reply.started":"2024-07-03T04:36:40.851458Z","shell.execute_reply":"2024-07-03T04:36:40.889804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"random.seed(3407)\nnp.random.seed(3407)\ntorch.manual_seed(3407)\n\ntrain_dl, valid_dl, le = load_train_data()\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\n\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:40.892682Z","iopub.execute_input":"2024-07-03T04:36:40.893043Z","iopub.status.idle":"2024-07-03T04:36:41.045942Z","shell.execute_reply.started":"2024-07-03T04:36:40.892994Z","shell.execute_reply":"2024-07-03T04:36:41.044909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1)\nmodel.fc = nn.Sequential(\n    nn.Linear(model.fc.in_features, 128),\n    nn.BatchNorm1d(128),\n    nn.ReLU(),\n    nn.Dropout(),\n    nn.Linear(128, len(le.classes_)))\nmodel.to(device)\n\nmodel","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:41.047192Z","iopub.execute_input":"2024-07-03T04:36:41.048027Z","iopub.status.idle":"2024-07-03T04:36:42.676823Z","shell.execute_reply.started":"2024-07-03T04:36:41.047977Z","shell.execute_reply":"2024-07-03T04:36:42.676010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.AdamW(\n    [{'params': [param for name, param in model.named_parameters() if 'fc.' not in name]},\n     {'params': model.fc.parameters(), 'lr': LR * 10}],\n    lr=LR, weight_decay=L2)\nscheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, EPOCHS, verbose=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:42.677889Z","iopub.execute_input":"2024-07-03T04:36:42.678177Z","iopub.status.idle":"2024-07-03T04:36:42.685822Z","shell.execute_reply.started":"2024-07-03T04:36:42.678154Z","shell.execute_reply":"2024-07-03T04:36:42.684832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for epoch in range(EPOCHS):\n    start = time.time()\n    \n    train_l = []\n    valid_l = []\n    \n    train_acc = []\n    valid_acc = []\n    \n    model.train()\n    for x, y in train_dl:\n        x, y = x.to(device), y.to(device, torch.int64)\n        optimizer.zero_grad()\n        y_hat = model(x)\n        l = loss(y_hat, y)\n        l.backward()\n        optimizer.step()\n        train_l.append(l.item())\n        train_acc.append(d2l.Classifier().accuracy(y_hat, y).item())\n    scheduler.step()\n    \n    model.eval()\n    with torch.no_grad():\n        for x, y in valid_dl:\n            x, y = x.to(device), y.to(device, torch.int64)\n            y_hat = model(x)\n            l = loss(y_hat, y)\n            valid_l.append(l.item())\n            valid_acc.append(d2l.Classifier().accuracy(y_hat, y).item())\n        print(f'{epoch}:'\n              f'train_l={np.mean(train_l):.6f},train_acc={np.mean(train_acc):.6f},'\n              f'valid_l={np.mean(valid_l):.6f},valid_acc={np.mean(valid_acc):.6f},'\n              f'time={time.time() - start:.6f}')","metadata":{"execution":{"iopub.status.busy":"2024-07-03T04:36:42.686939Z","iopub.execute_input":"2024-07-03T04:36:42.687285Z","iopub.status.idle":"2024-07-03T05:08:35.913330Z","shell.execute_reply.started":"2024-07-03T04:36:42.687251Z","shell.execute_reply":"2024-07-03T05:08:35.912078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = pd.read_csv('/kaggle/input/classify-leaves/test.csv')\n\nx = data['image']\nprint(f'x={len(x)}')\n\ntest_ds = LeaveDataset(x.values, x.values, False)\nprint(f'test={len(test_ds)}')\n\ntest_dl = DataLoader(test_ds, 128, shuffle=False, num_workers=3, persistent_workers=True)\nprint(f'test={len(test_dl)}')\n\nlabels = []\n\nfor x, _ in test_dl:\n    model.eval()\n    \n    y = model(x.to(device)).cpu().detach()\n    y = y.argmax(1)\n    y = le.classes_[y]\n    \n    for l in y:\n        labels.append(l)\n        \nsubmission = data\nsubmission['label'] = labels\nsubmission.to_csv('/kaggle/working/submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-07-03T05:08:35.915167Z","iopub.execute_input":"2024-07-03T05:08:35.915500Z","iopub.status.idle":"2024-07-03T05:09:00.499483Z","shell.execute_reply.started":"2024-07-03T05:08:35.915465Z","shell.execute_reply":"2024-07-03T05:09:00.498165Z"},"trusted":true},"execution_count":null,"outputs":[]}]}