{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom torch import nn\nfrom torch import optim\nimport torch.nn.functional as F\nfrom torchvision import datasets, transforms, models\nfrom PIL import Image\nfrom os import listdir\nimport pandas as pd","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_directory = '../input/train/train'\nepochs = 100","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_transforms = transforms.Compose([\n        transforms.RandomHorizontalFlip(),\n        transforms.RandomVerticalFlip(),\n        transforms.Resize(500),\n        transforms.CenterCrop(500),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\ntrain_data = datasets.ImageFolder(data_directory,transform=train_transforms)\ntrainloader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True)\ntest_transforms = transforms.Compose([\n        transforms.RandomHorizontalFlip(),\n        transforms.RandomVerticalFlip(),\n        transforms.Resize(500),\n        transforms.CenterCrop(500),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\ntest_data = datasets.ImageFolder(data_directory,transform=test_transforms,)\ntestloader = torch.utils.data.DataLoader(test_data, batch_size=32, shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class_names = trainloader.dataset.classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = models.resnet50(pretrained=True)\n# model = models.densenet161(pretrained=True)\nmodel.cuda()\n# print(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for param in model.parameters():\n    param.requires_grad = False\nmodel.fc = nn.Sequential(nn.Linear(2048, 512),\n                                 nn.ReLU(),\n                                 nn.Dropout(0.2),\n                                 nn.Linear(512, 5),\n                                 nn.LogSoftmax(dim=1))\ncriterion = nn.NLLLoss()\noptimizer = optim.Adam(model.fc.parameters(), lr=0.003)\n# criterion = nn.CrossEntropyLoss()\n# optimizer = optim.SGD(model.fc.parameters(), lr=0.003, momentum=0.9, weight_decay=5e-4)\nmodel.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"epoch_list, train_accuracy_list, test_accuracy_list, train_loss_list, validation_loss_list = [], [], [], [], []\nfor epoch in range(epochs):\n    train_loss = 0\n    val_loss = 0\n    accuracy = 0\n    # Training the model\n    model.train()\n    counter = 0\n    for inputs, labels in trainloader:\n        # Move to device\n        inputs, labels = inputs.to(device), labels.to(device)\n        # Clear optimizers\n        optimizer.zero_grad()\n        # Forward pass\n        output = model.forward(inputs)\n        # Loss\n        loss = criterion(output, labels)\n        # Calculate gradients (backpropogation)\n        loss.backward()\n        # Adjust parameters based on gradients\n        optimizer.step()\n        # Add the loss to the training set's rnning loss\n        train_loss += loss.item()*inputs.size(0)\n        # Print the progress of our training\n        counter += 1\n#         print(counter, \"/\", len(trainloader))\n    # Evaluating the model\n    model.eval()\n    counter = 0\n    # Tell torch not to calculate gradients\n    with torch.no_grad():\n        for inputs, labels in testloader:\n            # Move to device\n            inputs, labels = inputs.to(device), labels.to(device)\n            # Forward pass\n            output = model.forward(inputs)\n            # Calculate Loss\n            valloss = criterion(output, labels)\n            # Add loss to the validation set's running loss\n            val_loss += valloss.item()*inputs.size(0)\n            # Since our model outputs a LogSoftmax, find the real \n            # percentages by reversing the log function\n            output = torch.exp(output)\n            # Get the top class of the output\n            top_p, top_class = output.topk(1, dim=1)\n            # See how many of the classes were correct?\n            equals = top_class == labels.view(*top_class.shape)\n            # Calculate the mean (get the accuracy for this batch)\n            # and add it to the running accuracy for this epoch\n            accuracy += torch.mean(equals.type(torch.FloatTensor)).item()\n            # Print the progress of our evaluation\n            counter += 1\n#             print(counter, \"/\", len(testloader))\n    # Get the average loss for the entire epoch\n    train_loss = train_loss/len(trainloader.dataset)\n    train_loss_list.append(train_loss)\n    valid_loss = val_loss/len(testloader.dataset)\n    validation_loss_list.append(valid_loss)\n    train_acc = accuracy/len(trainloader)\n    train_accuracy_list.append(train_acc)\n    test_acc = accuracy/len(testloader)\n    test_accuracy_list.append(test_acc)\n    epoch_list.append(epoch)\n#     print(f'Epoch: {epoch}, Accuracy: {acc}, Train loss: {train_loss}, Valid loss: {valid_loss}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"max_train_accuracy = max(train_accuracy_list)\nmax_test_accuracy = max(test_accuracy_list)\nepoch_train = epoch_list[train_accuracy_list.index(max_train_accuracy)]\nepoch_test = epoch_list[test_accuracy_list.index(max_test_accuracy)]\nprint(f'Max Accuracy Score: {max_train_accuracy}, Epoch: {epoch_train}')\nprint(f'Max Accuracy Score: {max_test_accuracy}, Epoch: {epoch_test}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs = range(1, len(train_accuracy_list) + 1)\n#Train and validation accuracy\nplt.plot(epochs, train_accuracy_list, 'b', label='Train accurarcy')\nplt.plot(epochs, test_accuracy_list, 'r', label='Validation accurarcy')\nplt.title('Training and Validation accurarcy')\nplt.legend()\n\nplt.figure()\n#Train and validation loss\nplt.plot(epochs, train_loss_list, 'b', label='Training loss')\nplt.plot(epochs, validation_loss_list, 'r', label='Validation loss')\nplt.title('Training and Validation loss')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.eval()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def process_image(image_dir):\n    # Process a PIL image for use in a PyTorch model\n    # tensor.numpy().transpose(1, 2, 0)\n    image = Image.open(image_dir)\n    preprocess = transforms.Compose([\n        transforms.Resize(500),\n        transforms.CenterCrop(450),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n    ])\n    image = preprocess(image)\n    # Convert 2D image to 1D vector\n    image = np.expand_dims(image, 0)\n    image = torch.from_numpy(image)\n    inputs = image.to(device)\n    return inputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Using our model to predict the label\ndef predict(image, model):\n    # Pass the image through our model\n    output = model.forward(image)\n    # Reverse the log function in our output\n    output = torch.exp(output)\n    # Get the top predicted class, and the output percentage for\n    # that class\n    probs, classes = output.topk(1, dim=1)\n    return probs.item(), classes.item()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_directory = '../input/test/test/0'\npredictions, test_image_fileName = [], []\ntry:\n    test_images = listdir(test_directory)\n    for images in test_images:\n        test_image_fileName.append(images)\n        image = process_image(f'{test_directory}/{images}')\n        top_prob, top_class = predict(image, model)\n        predictions.append(class_names[top_class])\nexcept Exception as e:\n    print(e)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"[INFO] Creating pandas dataframe\")\nsubmission_data = {\"Category\":predictions,\"Id\":test_image_fileName,}\nsubmission_data_frame = pd.DataFrame(submission_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_data_frame.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"[INFO] Saving Predicition to CSV\")\nsubmission_data_frame.to_csv('sample-submission.csv',columns=[\"Category\",\"Id\"], index = False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}