{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Remarques:\n1. This is a simple binary classification model of resnet50 with pre-trained parameters loaded from the pytorch library (based on the imagenet classification task), so even if I don't optimize it I get to 0.99.  \n2. I ran the code on my own computer, my computer configuration is RTX A6000, so I chose larger image size, you can change it.  \n3. Due to the slow training process, I only used epoch=1 as an example, I actually trained on my computer for 25 epochs (about half an hour). Also, although I split the validation set, I didn't use it (I just wanted to try it out, didn't expect the model to perform very well). In fact, we should add an evaluation phase to choose the best model based on the results on the validation set....You guys can optimize this.  \n\n\n","metadata":{}},{"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\ntest_path_list = []\ntrain_path_list = []\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        #print(dirname)\n        if 'test' in dirname:\n            test_path_list.append(os.path.join(dirname, filename))\n        if 'train' in dirname:\n            train_path_list.append(os.path.join(dirname, filename))\n            \n\n\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","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(test_path_list))\nprint(len(train_path_list))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"cat 0 dag 1","metadata":{}},{"cell_type":"code","source":"label_list = []\nfor i in train_path_list:\n    #print(i)\n    if 'cats' in i:\n        label_list.append(0)\n    if 'dogs' in i:\n        label_list.append(1)\nprint(len(label_list))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# pytorch resnet50","metadata":{}},{"cell_type":"code","source":"import os\nimport time\nimport torch.nn as nn\nimport torch\nimport torchvision.transforms as transforms\nfrom PIL import Image\nfrom matplotlib import pyplot as plt\nimport torchvision.models as models\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nfrom tqdm.notebook import tqdm\n\n#from torch.utils.tensorboard import SummaryWriter\nfrom torch.optim.lr_scheduler import ExponentialLR","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.tensorboard import SummaryWriter\n\nsummaryWriter = SummaryWriter(\"./logs/\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\nprint('device =',device)\nprint(torch.cuda.get_device_name(0))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(Dataset):#需要继承data.Dataset\n    def __init__(self,\n                 path_list,\n                 label_list,\n                 data_augmentation_function=None):\n        self.path_list = path_list\n        self.label_list = label_list\n        self.__data_augmentation_function = data_augmentation_function\n        self.toTensor = transforms.Compose([transforms.Resize((256,256)),transforms.ToTensor(),\n                                             transforms.Normalize([0.5], [0.5])])\n        \n    def __getitem__(self, index):\n        # TODO\n        # 1. Read one data from file (e.g. using numpy.fromfile, PIL.Image.open).\n        # 2. Preprocess the data (e.g. torchvision.Transform).\n        # 3. Return a data pair (e.g. image and label).\n        #这里需要注意的是，第一步：read one data，是一个data\n        image_path = str(self.path_list[index])\n        image = Image.open(image_path)\n        im_aug = transforms.Compose([\n            transforms.RandomHorizontalFlip(),\n            transforms.RandomRotation(45),\n            transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5)\n        ])\n        if self.__data_augmentation_function is not None:\n            image = im_aug(image)\n            \n        image = self.toTensor(image)\n        label = np.array(self.label_list[index])\n        return image, label\n        \n        \n    def __len__(self):\n        # You should change 0 to the total size of your dataset.\n        return len(self.path_list)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train,X_test,y_train,y_test = train_test_split(train_path_list,label_list,test_size = 0.15,random_state = 1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_set = CustomDataset(X_train,y_train)\nval_set = CustomDataset(X_test,y_test)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs=1  #总样本循环次数\nbatch_size=128\ntrain_loader = DataLoader(dataset = train_set, batch_size = batch_size, shuffle = True)\ntest_loader = DataLoader(dataset = val_set,batch_size = batch_size, shuffle = False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_batch(batch, row=2, col=2, channel_first=True):\n    if isinstance(batch, tuple) or isinstance(batch, list):\n        imgs, tars = batch\n    else:\n        imgs, tars = batch, None\n    plt.figure(figsize=(col*3, row*3))\n    for i in range(row*col):\n        plt.subplot(row, col, i+1)\n        img = imgs[i].numpy()\n        if channel_first:\n            img = img.transpose((1, 2, 0))\n        plt.imshow(img)#plt.imshow((img * 255).astype(np.uint8)) 如果0-1的话\n        if tars is not None:\n            plt.title(tars[i])\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch = iter(train_loader).next()\nplot_batch(batch, row=2, col=5)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_model():\n    resnet50 = models.resnet50(pretrained=True)\n    fc_inputs = resnet50.fc.in_features\n    #resnet50.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)\n    resnet50.fc = nn.Linear(fc_inputs, 2)\n    #print(resnet50)\n    return resnet50","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = create_model()\nmodel.to(device)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\ncriterion = nn.CrossEntropyLoss()\nscheduler = ExponentialLR(optimizer, gamma=0.99)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.train()\ntotal_step = len(train_loader)\nfor epoch in range(num_epochs):\n    per_epoch_loss = 0\n    num_correct= 0\n    \n    for x,label in tqdm(train_loader):\n        x = x.to(device)\n        label = label.to(device)\n        # Forward pass\n        logits = model(x)\n        loss = criterion(logits, label)\n        \n        per_epoch_loss += loss.item()\n        \n        # Backward and optimize\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        pred = logits.argmax(dim=1)\n        num_correct += torch.eq(pred, label).sum().float().item()\n            \n    print(\"Train Epoch: {}\\t Loss: {:.6f}\\t Acc: {:.6f}\".format(epoch,per_epoch_loss/total_step,num_correct/len(train_loader.dataset)))\n    summaryWriter.add_scalars('loss', {\"loss\":(per_epoch_loss/total_step)}, epoch)\n    summaryWriter.add_scalars('acc', {\"acc\":num_correct/len(train_loader.dataset)}, epoch)\n    scheduler.step()\n    \n    #filepath = \"./weights\"\n    #folder = os.path.exists(filepath)\n    #if not folder:\n    #    # 判断是否存在文件夹如果不存在则创建为文件夹\n    #    os.makedirs(filepath)\n    #path = './weights/model' + str(epoch) + '.pth'\n    #torch.save(model.state_dict(), path)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The code after this does not run directly, but uses the trained model to make predictions on the test set, kaggle's training is too slow so I directly load the results... I run it on my computer. After 25 epochs, you can get the same results as me!","metadata":{}},{"cell_type":"code","source":"output = pd.read_csv('../input/submission-li/submission_pytorch.csv')# you should load sample_submission for prediction, here i just for show the results.\nprint(output)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test1 = output['id'].tolist()\ntest_path_list = []\nfor i in test1:\n    test_path_list.append('./test/test/'+str(i))\nprint(test_path_list)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_set = CustomDataset(test_path_list,[0]*len(test_path_list))\nprint(len(test_set))\ntest_loader = DataLoader(dataset = test_set,batch_size = batch_size, shuffle = False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pre_list = []\nmodel.eval()\n'''\nwith torch.no_grad():\n    for x,label in tqdm(test_loader):\n        x = x.to(device)\n        #label = label.to(device)\n        # Forward pass\n        logits = model(x)\n        \n        pred = logits.argmax(dim=1)\n        #print(len)\n        for i in pred:\n            pre_list.append(i.item())\n'''","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#output.labels = pre_list\nprint(output)\noutput.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}