{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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":30698,"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-05-19T03:58:03.101313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%matplotlib inline\nimport torch\nfrom torch.utils import data as Data\nimport torchvision\nfrom torch import nn\nfrom d2l import torch as d2l\n\nimport os\nimport pandas as pd\nimport random","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imgpath = \"/kaggle/input/classify-leaves\"\ntrainlist = pd.read_csv(f\"{imgpath}/train.csv\")\nnum2name = list(trainlist[\"label\"].value_counts().index)\nrandom.shuffle(num2name)\nname2num = {}\nfor i in range(len(num2name)):\n    name2num[num2name[i]] = i\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def try_gpu():\n    if(torch.cuda.device_count()>0):\n        return torch.device('cuda')\n    return torch.device('cpu')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_path = '/kaggle/working/pre_res_model.ckpt'\ndef save_model(net):\n    torch.save(net.state_dict(),model_path)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nclass Leaf_data(Data.Dataset):\n    def __init__(self,path,train,transform=lambda x:x) -> None:\n        super().__init__()\n        self.path = path\n        self.transform = transform\n        self.train = train\n        if train:\n            self.datalist = pd.read_csv(f\"{path}/train.csv\")\n        else:\n            self.datalist = pd.read_csv(f\"{path}/test.csv\")\n    def __getitem__(self, index):\n        res = ()\n        tmplist = self.datalist.iloc[index,:]\n        for i in tmplist.index:\n            if(i==\"image\"):\n                res += self.transform(d2l.Image.open(f\"{self.path}/{tmplist[i]}\")),\n            else:\n                res += name2num[tmplist[i]],\n        if(len(res)<2):\n            res+= tmplist[i],\n        return res\n    def __len__(self)->int:\n        return len(self.datalist)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_batch(X,y,net,loss,trainer,devices):\n    if isinstance(X,list):\n        X = [x.to(devices) for x in X]\n    else:\n        X = X.to(devices)\n    y = y.to(devices)\n    net.train()\n    trainer.zero_grad()\n    pred = net(X)\n    l = loss(pred,y)\n    l.sum().backward()\n    trainer.step()\n    LR_con.step()\n    return l.sum(),d2l.accuracy(pred,y)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef train(train_data,test_data,net,loss,trainer,num_epochs,device = try_gpu()):\n    best_acc = 0\n    timer = d2l.Timer()\n    plot = d2l.Animator(xlabel=\"epoch\",xlim=[1,num_epochs],legend=['train loss','train acc','test loss'],ylim=[0,1])\n    for epoch in range(num_epochs):\n        # Sum of training loss, sum of training accuracy, no. of examples,\n        # no. of predictions\n        metric = d2l.Accumulator(4)\n        for i, (features, labels) in enumerate(train_data):\n            timer.start()\n            l, acc = train_batch(\n                features, labels, net, loss, trainer, device)\n            metric.add(l, acc, labels.shape[0], labels.numel())\n            timer.stop()\n        test_acc = d2l.evaluate_accuracy_gpu(net, test_data,device=device)\n        if(test_acc>best_acc):\n            save_model(net)\n            best_acc = test_acc\n        plot.add(epoch + 1, (metric[0] / metric[2], metric[1] / metric[3], test_acc))\n        print(f'loss {metric[0] / metric[2]:.3f}, train acc '\n          f'{metric[1] / metric[3]:.3f}, test acc {test_acc:.3f}')\n    print()\n    print(f'loss {metric[0] / metric[2]:.3f}, train acc '\n          f'{metric[1] / metric[3]:.3f}, test acc {test_acc:.3f}')\n    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec on '\n          f'{str(device)}')\n    print(f\"best acc {best_acc}\")\n    return metric[0] / metric[2],metric[1] / metric[3],test_acc\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def init_weight(m):\n    if type(m) in [nn.Linear,nn.Conv2d]:\n        nn.init.xavier_normal_(m.weight)\nnet = torchvision.models.resnet34(weights=torchvision.models.ResNet34_Weights.IMAGENET1K_V1)\nnet.fc = nn.Linear(in_features=512, out_features=len(name2num), bias=True)\nnet.fc.apply(init_weight)\nnet.to(try_gpu())\nlr = 1e-4\nparames = [parame for name,parame in net.named_parameters() if name not in [\"fc.weight\",\"fc.bias\"]]\ntrainer = torch.optim.Adam([{\"params\":parames},\n                            {\"params\":net.fc.parameters(),\"lr\":lr*10}],lr=lr)\nLR_con = torch.optim.lr_scheduler.CosineAnnealingLR(trainer,1,0)\nloss = nn.CrossEntropyLoss(reduction='none')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch = 64\nnum_epochs = 10\nnorm = torchvision.transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])\naugs = torchvision.transforms.Compose([\n    torchvision.transforms.Resize(224),\n    torchvision.transforms.RandomHorizontalFlip(p=0.5),\n    torchvision.transforms.ToTensor(),norm\n])\ntrain_data,valid_data = Data.random_split(\n    dataset=Leaf_data(imgpath,True,augs),\n    lengths=[0.8,0.2]\n)\ntrain_dataloder = Data.DataLoader(train_data,batch,True)\nvalid_dataloder = Data.DataLoader(valid_data,batch,True)\n\ntrain(train_dataloder,valid_dataloder,net,loss,trainer,num_epochs)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"net.load_state_dict(torch.load(model_path))\naugs = torchvision.transforms.Compose([\n    torchvision.transforms.Resize(224),\n    torchvision.transforms.ToTensor(),norm\n])\ntest_data = Leaf_data(imgpath,False,augs)\ntest_dataloader = Data.DataLoader(test_data,batch_size=64,shuffle=False)\nres = pd.DataFrame(columns = [\"image\",\"label\"],index=range(len(test_data)))\nnet = net.cpu()\ncount = 0\nfor X,y in test_dataloader:\n    preds = net(X).detach().argmax(dim=-1).numpy()\n    preds = pd.DataFrame(y,index=map(lambda x:num2name[x],preds))\n    preds.loc[:,1] = preds.index\n    preds.index = range(count,count+len(y))\n    res.iloc[preds.index] = preds\n    count+=len(y)\n    print(f\"loaded {count}/{len(test_data)} datas\")\nres.to_csv('/kaggle/working/submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-05-19T04:46:49.302170Z","iopub.execute_input":"2024-05-19T04:46:49.302502Z","iopub.status.idle":"2024-05-19T04:53:38.760381Z","shell.execute_reply.started":"2024-05-19T04:46:49.302477Z","shell.execute_reply":"2024-05-19T04:53:38.759320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"res.to_csv('/kaggle/working/submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-05-19T04:54:42.963780Z","iopub.execute_input":"2024-05-19T04:54:42.964416Z","iopub.status.idle":"2024-05-19T04:54:42.991957Z","shell.execute_reply.started":"2024-05-19T04:54:42.964387Z","shell.execute_reply":"2024-05-19T04:54:42.991113Z"},"trusted":true},"execution_count":null,"outputs":[]}]}