{"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":"code","source":"# import libraries\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport torch\nimport os\nimport torch.nn.functional as F\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision.datasets as datasets\nfrom torchvision import models\nimport torchvision.transforms as transforms\nimport torch.optim as optim\nfrom skimage import io\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nimport cv2\n%matplotlib inline","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:09.188256Z","iopub.execute_input":"2022-10-21T17:22:09.188618Z","iopub.status.idle":"2022-10-21T17:22:09.203629Z","shell.execute_reply.started":"2022-10-21T17:22:09.188586Z","shell.execute_reply":"2022-10-21T17:22:09.201567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# display first nXm images\ndef plot_images(rows, columns, images):\n    '''\n    Plot first 100 images\n    INPUTS:\n        rows: number of rows we want to display images on it\n        columns: number of images we want to display in each row\n        images: consist of 100 images each image consist 224*224 pixels\n        labels: truth value for each image\n    '''\n    \n    fig, x= plt.subplots(rows, columns, constrained_layout=True,figsize=(15,8))\n    plt.setp(x, xticks=[], yticks=[])\n    for i in range (len(x)):\n        for j in range (len(x[0])):\n            index = i*columns+j\n            img = cv2.imread('../input/dog-breed-identification/train/' + images[index])\n            x[i,j].imshow(cv2.resize(img, (224, 224)))\n            \nnum_columns = 5\ntrain_data = os.listdir('../input/dog-breed-identification/train')[:100]\nplot_images(num_columns, num_columns, train_data)","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:09.342222Z","iopub.execute_input":"2022-10-21T17:22:09.343084Z","iopub.status.idle":"2022-10-21T17:22:11.214263Z","shell.execute_reply.started":"2022-10-21T17:22:09.343046Z","shell.execute_reply":"2022-10-21T17:22:11.213291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# mapping labels same order of sample_submittion.csv\nmap_labels = dict()\nfor index, value in enumerate(pd.read_csv('../input/dog-breed-identification/sample_submission.csv').columns[1:]):\n    map_labels[value] = index","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:11.216414Z","iopub.execute_input":"2022-10-21T17:22:11.217185Z","iopub.status.idle":"2022-10-21T17:22:11.819322Z","shell.execute_reply.started":"2022-10-21T17:22:11.217130Z","shell.execute_reply":"2022-10-21T17:22:11.818341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load custom dataset\nclass DogBreedsDataset_train(Dataset):\n    def __init__(self, csv_file, root_dir, transform=None):\n        self.labels = pd.read_csv(csv_file)\n        self.root_dir = root_dir\n        self.transform = transform['train']\n        \n    def __len__(self):\n        return self.labels.shape[0]\n    \n    def __getitem__(self, index):\n        img_path = os.path.join(self.root_dir, self.labels.iloc[index, 0])+'.jpg'\n        image = io.imread(img_path)\n        y_label = torch.tensor(int(map_labels[self.labels.iloc[index, 1]]))\n\n        if self.transform:\n            image = self.transform(image)\n\n        return (image, y_label)\n\n        \n        ","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:11.820648Z","iopub.execute_input":"2022-10-21T17:22:11.821011Z","iopub.status.idle":"2022-10-21T17:22:11.829631Z","shell.execute_reply.started":"2022-10-21T17:22:11.820975Z","shell.execute_reply":"2022-10-21T17:22:11.828432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load custom dataset\nclass DogBreedsDataset_test(Dataset):\n    def __init__(self, csv_file, root_dir, transform=None):\n        self.name_images = pd.read_csv(csv_file)['id'].values\n        self.root_dir = root_dir\n        self.transform = transform['test']\n    \n        \n    def __len__(self):\n        return len(self.name_images)\n    \n    def __getitem__(self, index):\n        img_path = os.path.join(self.root_dir, self.name_images[index])+'.jpg'\n        image = io.imread(img_path)\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:11.832765Z","iopub.execute_input":"2022-10-21T17:22:11.833414Z","iopub.status.idle":"2022-10-21T17:22:11.842137Z","shell.execute_reply.started":"2022-10-21T17:22:11.833378Z","shell.execute_reply":"2022-10-21T17:22:11.841017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Hyperparameters\nin_channel = 3\nnum_classes = 120\nlearning_rate = 1e-4\nbatch_size = 512\nnum_epochs = 300","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:11.843716Z","iopub.execute_input":"2022-10-21T17:22:11.844412Z","iopub.status.idle":"2022-10-21T17:22:11.855437Z","shell.execute_reply.started":"2022-10-21T17:22:11.844361Z","shell.execute_reply":"2022-10-21T17:22:11.854439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# images preprocessing\ntransform ={'train': transforms.Compose([\n        transforms.ToPILImage(),\n        transforms.RandomResizedCrop(size=256, scale=(0.95, 1.0)),\n        transforms.RandomRotation(degrees=15),\n        transforms.ColorJitter(),\n        transforms.RandomHorizontalFlip(),\n        transforms.CenterCrop(size=224),  # Image net standards\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406],\n                             [0.229, 0.224, 0.225])]),  # Imagenet standards\n    'test': transforms.Compose([transforms.ToPILImage(),\n                                      transforms.RandomResizedCrop(size=256, scale=(0.95, 1.0)),\n                                      transforms.CenterCrop(size=224),\n                                      transforms.ToTensor(),\n                                     transforms.Normalize([0.485, 0.456, 0.406],\n                                                          [0.229, 0.224, 0.225])])}\n\ndataset = DogBreedsDataset_train('../input/dog-breed-identification/labels.csv', '../input/dog-breed-identification/train', transform)\n# Random split data to 70% training and 30% validation\ntrain_set_size = int(len(dataset) * 0.7)\nvalid_set_size = len(dataset) - train_set_size\ntrain_set, valid_set = torch.utils.data.random_split(dataset, [train_set_size, valid_set_size])\ntrain_loader = DataLoader(dataset=train_set, batch_size=batch_size, shuffle=True)\nvalid_loader = DataLoader(dataset=valid_set, batch_size=batch_size, shuffle=True)\n\n# loading testing data\ntest_data = DogBreedsDataset_test('../input/dog-breed-identification/sample_submission.csv', '../input/dog-breed-identification/test', transform=transform)\ntest_loader = DataLoader(test_data, batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:11.859386Z","iopub.execute_input":"2022-10-21T17:22:11.860067Z","iopub.status.idle":"2022-10-21T17:22:12.184942Z","shell.execute_reply.started":"2022-10-21T17:22:11.860041Z","shell.execute_reply":"2022-10-21T17:22:12.183896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set device cuda for GPU if it's available otherwise run on the CPU\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:12.186854Z","iopub.execute_input":"2022-10-21T17:22:12.187319Z","iopub.status.idle":"2022-10-21T17:22:12.193706Z","shell.execute_reply.started":"2022-10-21T17:22:12.187278Z","shell.execute_reply":"2022-10-21T17:22:12.192592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save checkpoint\ndef save_checkpoint(state, filename=\"my_checkpoint.pth.tar\"):\n    print(\"=> Saving checkpoint\")\n    torch.save(state, filename)\n\n# load checkpint\ndef load_checkpoint(checkpoint, model, optimizer):\n    print(\"=> Loading checkpoint\")\n    model.load_state_dict(checkpoint[\"state_dict\"])\n    optimizer.load_state_dict(checkpoint[\"optimizer\"])\n\n    \n","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:12.195507Z","iopub.execute_input":"2022-10-21T17:22:12.196559Z","iopub.status.idle":"2022-10-21T17:22:12.205032Z","shell.execute_reply.started":"2022-10-21T17:22:12.196517Z","shell.execute_reply":"2022-10-21T17:22:12.204086Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load model architecture with weights (resnet50) \nmodel = models.resnet50(pretrained=True)\n\n# freeze all layers \nfor param in model.parameters():\n    param.requires_grad = False\n    \n# replace last layer with from 1000 classes to be 120 classes\nmodel.fc = nn.Linear(2048, 120)\nmodel = model.to(device=device)\nmodel","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:12.206586Z","iopub.execute_input":"2022-10-21T17:22:12.207686Z","iopub.status.idle":"2022-10-21T17:22:12.809373Z","shell.execute_reply.started":"2022-10-21T17:22:12.207648Z","shell.execute_reply":"2022-10-21T17:22:12.808455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loss function\ncriterion = nn.CrossEntropyLoss()\n# optimizer\noptimizer = optim.Adam(model.parameters(), lr=learning_rate)\n# checkpoint to save and load model\ncheckpoint = {\"state_dict\": model.state_dict(), \"optimizer\": optimizer.state_dict()}","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:47.121390Z","iopub.execute_input":"2022-10-21T17:22:47.121757Z","iopub.status.idle":"2022-10-21T17:22:47.131848Z","shell.execute_reply.started":"2022-10-21T17:22:47.121725Z","shell.execute_reply":"2022-10-21T17:22:47.129912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def traindata(device, model, epochs, optimizer, loss_function, train_loader, valid_loader):\n    # Early stopping\n    best_loss = 100\n    patience = 5\n    triggertimes = 0\n    \n    for epoch in range(1, epochs+1):\n        model.train()\n        correct = 0\n        loss_total = 0\n        for data in train_loader:\n            input = data[0].to(device)\n            label = data[1].to(device)\n\n            # Zero the gradients\n            optimizer.zero_grad()\n\n            # Forward and backward propagation\n            output = model(input)\n            _, predicted = output.max(1)\n            loss = loss_function(output, label)\n            loss_total += loss.item()\n            correct+= (predicted == label).sum()\n            loss.backward()\n            optimizer.step()\n        print('epoch number: {}'.format(epoch))\n        print('Training Accuracy: {} Training loss: {}'.format(correct/len(train_loader.sampler), loss_total/len(train_loader)))\n        \n        # Early stopping\n        current_loss = validation(model, device, valid_loader, loss_function)\n        print('The Current Loss:', current_loss)\n        print('Best Loss:', best_loss)\n\n        if current_loss > best_loss:\n            trigger_times += 1\n            print('Trigger Times:', trigger_times)\n\n            if trigger_times >= patience:\n                print('Early stopping!\\nStart to test process.')\n                return model\n\n        else:\n            print('trigger times: 0')\n            trigger_times = 0\n            save_checkpoint(checkpoint)\n            best_loss = current_loss\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:47.851024Z","iopub.execute_input":"2022-10-21T17:22:47.851391Z","iopub.status.idle":"2022-10-21T17:22:47.862489Z","shell.execute_reply.started":"2022-10-21T17:22:47.851360Z","shell.execute_reply":"2022-10-21T17:22:47.861373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def validation(model, device, valid_loader, loss_function):\n\n    model.eval()\n    loss_total = 0\n    correct = 0\n    # Test validation data\n    with torch.no_grad():\n        for data in valid_loader:\n            input = data[0].to(device)\n            label = data[1].to(device)\n\n            output = model(input)\n            _, predicted = output.max(1)\n            loss = loss_function(output, label)\n            loss_total += loss.item()\n            correct+= (predicted == label).sum()\n        print('Validation Accuracy: {}'.format(correct/len(valid_loader.sampler)))\n    return loss_total / len(valid_loader)","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:48.030142Z","iopub.execute_input":"2022-10-21T17:22:48.030517Z","iopub.status.idle":"2022-10-21T17:22:48.037584Z","shell.execute_reply.started":"2022-10-21T17:22:48.030484Z","shell.execute_reply":"2022-10-21T17:22:48.036382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test(device, model, test_loader, loss_function):\n\n    model.eval()\n    predictions = pd.DataFrame()\n    with torch.no_grad():\n        for data in test_loader:\n            input = data.to(device)\n\n            output = model(input)\n            m = nn.Softmax(dim=1)\n            res = m(output)\n            predictions = pd.concat([predictions, pd.DataFrame(torch.Tensor.cpu(res).numpy(), columns = list(map_labels.keys()))], ignore_index=True)\n            \n        return (predictions)","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:48.197018Z","iopub.execute_input":"2022-10-21T17:22:48.197314Z","iopub.status.idle":"2022-10-21T17:22:48.204450Z","shell.execute_reply.started":"2022-10-21T17:22:48.197288Z","shell.execute_reply":"2022-10-21T17:22:48.202951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"  model = traindata(device, model, num_epochs, optimizer, criterion, train_loader, valid_loader)","metadata":{"execution":{"iopub.status.busy":"2022-10-21T17:22:48.376004Z","iopub.execute_input":"2022-10-21T17:22:48.376306Z","iopub.status.idle":"2022-10-21T17:23:08.872705Z","shell.execute_reply.started":"2022-10-21T17:22:48.376280Z","shell.execute_reply":"2022-10-21T17:23:08.870718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"load_checkpoint(torch.load(\"my_checkpoint.pth.tar\"), model, optimizer)","metadata":{"execution":{"iopub.status.busy":"2022-10-21T15:06:25.983353Z","iopub.execute_input":"2022-10-21T15:06:25.983760Z","iopub.status.idle":"2022-10-21T15:06:26.114101Z","shell.execute_reply.started":"2022-10-21T15:06:25.983719Z","shell.execute_reply":"2022-10-21T15:06:26.112881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = test(device, model, test_loader, criterion)\nids = pd.DataFrame(pd.read_csv('../input/dog-breed-identification/sample_submission.csv')['id'].values, columns=['id'])\nfinal_df = pd.concat([ids, df], ignore_index=True, axis=1)\nfinal_df.columns = pd.read_csv('../input/dog-breed-identification/sample_submission.csv').columns","metadata":{"execution":{"iopub.status.busy":"2022-10-21T15:06:27.795727Z","iopub.execute_input":"2022-10-21T15:06:27.796415Z","iopub.status.idle":"2022-10-21T15:09:45.534289Z","shell.execute_reply.started":"2022-10-21T15:06:27.796378Z","shell.execute_reply":"2022-10-21T15:09:45.533168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_df.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}