{"cells":[{"metadata":{},"cell_type":"markdown","source":"STEP1 - IMPORTED ALL NECESSARY LIBRARIES"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport copy\nfrom PIL import Image\n\nimport torch\nimport torch.nn as nn\nimport torchvision\nimport torchvision.datasets as datasets\nimport torchvision.models as models\nfrom torchvision import transforms\nfrom sklearn.metrics import confusion_matrix, f1_score, recall_score, precision_score, classification_report, accuracy_score\nfrom torch.utils.data import random_split\nimport csv","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"STEP2- CHECKED FOR GPU"},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint(device)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"driver_imgs_list.csv contains a list of training images, their subject id and class label id. "},{"metadata":{"trusted":true},"cell_type":"code","source":"data = pd.read_csv(\"../input/state-farm-distracted-driver-detection/driver_imgs_list.csv\")\ndata.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data['subject'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We get to know that there are 26 different drivers in training images.."},{"metadata":{},"cell_type":"markdown","source":"STEP3- LOADED THE DATASET AND DIVIDED INTO TEST AND TRAIN SET."},{"metadata":{"trusted":true},"cell_type":"code","source":"data.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ntransform = transforms.Compose([\n    transforms.Resize(256),\n    transforms.CenterCrop(224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset = torchvision.datasets.ImageFolder(root='../input/state-farm-distracted-driver-detection/imgs/train', transform=transform)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train, test = random_split(dataset, [15696, 6728])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 32\ntrainloader = torch.utils.data.DataLoader(train, batch_size=batch_size, shuffle=True)\ntestloader = torch.utils.data.DataLoader(test, batch_size=batch_size, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataiter = iter(trainloader)\nimages, labels = dataiter.next()\n\nprint(images.shape)#input image shape\nprint(labels.shape)#label shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#classes is a list of labels for all 10 classes.\nclasses = ['safe driving', 'texting - right', 'talking on the phone - right', 'texting - left', 'talking on the phone - left', 'operating the radio', 'drinking', 'reaching behind', 'hair and makeup', 'talking to passenger']","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"STEP4- BUILT THE EVALUATION AND TRAINING FUNCTION TO BE FURTHER USED BY THE MODELS."},{"metadata":{"trusted":true},"cell_type":"code","source":"#evaluation function used to calculate accuracy of a model.\ndef evaluation(dataloader, model):\n    total, correct = 0, 0\n    model.eval()\n    for data in dataloader:\n        inputs, labels = data\n        inputs = inputs.to(device)\n        labels = labels.to(device)\n        outputs = model(inputs)\n        _, pred = torch.max(outputs.data, 1)\n        total += labels.size(0)\n        correct += (pred == labels).sum().item()\n    return 100 * correct / total","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#train function to train a particular model. Here we have set epochs as 8.\ndef train(model):\n    loss_epoch_arr = []\n    max_epochs = 8\n    min_loss = 1000\n    for epoch in range(max_epochs):\n        for i, data in enumerate(trainloader, 0):\n            inputs,labels = data\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            opt.zero_grad()\n            model.train()\n            outputs = model(inputs)\n            loss = loss_fn(outputs, labels)\n            loss.backward()\n            opt.step()\n            if min_loss > loss.item():\n                min_loss = loss.item()\n                best_model = copy.deepcopy(model.state_dict())\n                print('Min loss %0.2f' % min_loss)\n            \n            del inputs, labels, outputs\n            torch.cuda.empty_cache()\n        loss_epoch_arr.append(loss.item())\n        model.eval()\n        print('Epoch: %d/%d, Test acc: %0.2f, Train acc: %0.2f' % (\n        epoch, max_epochs, \n        evaluation(testloader, model), evaluation(trainloader, model)))\n    plt.plot(loss_epoch_arr)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"STEP5- CREATED MODELS-"},{"metadata":{},"cell_type":"markdown","source":"OUR FIRST MODEL IS BUILT USING TRANSFER LEARNING. A RESNET MODEL IS LOADED AND SOME EXTRA LAYERS ARE ADDED TO THE END. WE NAMED THIS AS 'model1'."},{"metadata":{"trusted":true},"cell_type":"code","source":"#Downloaded resnet model\nmodel1 = torchvision.models.resnet50(pretrained=True, progress=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#We have loaded pretrained model..so we have set the parameters as no training required.\nfor p in model1.parameters():\n    p.requires_grad = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Added some layers in model1\nmodel1.fc = nn.Sequential(nn.Linear(2048, 1024),\n                           nn.ReLU(),\n                           nn.Linear(1024, 512),\n                           nn.ReLU(),                       \n                           nn.Linear(512, 10),\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#The layer added needs training \nfor param in model1.parameters():\n    if param.requires_grad:\n        print(param.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Trained model1\nimport torch.optim as optim\nlearning_rate = 0.001\nmomentum = 0.9\nmodel1 = model1.to(device)\nopt = optim.Adam(model1.parameters(), lr=learning_rate)\nloss_fn = nn.CrossEntropyLoss()\ntrain(model1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"BUILT SECOND MODEL WHICH CONTAINS VARIOUS CONVOLUTIONAL LAYERS AND LINEAR LAYERS. WE NAMED IT AS 'model2'"},{"metadata":{"trusted":true},"cell_type":"code","source":"# second model\nclass Net(nn.Module):\n    def __init__(self):\n        super(Net, self).__init__()\n        \n        self.convblock = nn.Sequential(\n            nn.Conv2d(3, 32, 5, stride = (1,1), padding = 2),   #(N,3,224,224)-> (N,32,224,224)\n            nn.BatchNorm2d(32), \n            nn.ReLU(),\n            nn.MaxPool2d(2,2),     #(N,32,224,224)->(N,32,112,112)\n            nn.Conv2d(32, 64, 5, stride = (1,1), padding = 2),  #(N,32,112,112)->(N,64,112,112)\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.MaxPool2d(2,2),     #(N,64,112,112)->(N,64,56,56)\n            nn.Conv2d(64, 128, 5, stride = (1,1), padding = 2), #(N,64,56,56) ->(N,128,56,56)\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.MaxPool2d(2,2),    #(N,128,56,56)->(N,128,28,28)\n            nn.Conv2d(128, 256, 5, stride = (1,1), padding = 2), #(N,128,28,28)->(N,256,28,28)\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n            nn.MaxPool2d(2,2),  #(N,256,28,28)->(N,256,14,14)\n            nn.Conv2d(256, 256, 5, stride = (1,1), padding = 2), #(N,256,14,14)->(N,256,14,14)\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n            nn.MaxPool2d(2,2)   #(N,256,14,14)->(N,256,7,7)\n            \n            \n        )\n        self.denseblock = nn.Sequential(\n            nn.Linear(12544, 1024),\n            nn.ReLU(),\n            nn.Linear(1024,512),\n            nn.ReLU(),\n            nn.Linear(512,10)\n        )\n        \n    def forward(self, x):\n        x = self.convblock(x)\n        x = x.view(x.size(0),-1)\n        x = self.denseblock(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Trained model2\nmodel2 = Net()\nmodel2 = model2.to(device)\nlearning_rate = 0.001\nmomentum = 0.9\nmodel1 = model1.to(device)\nopt = optim.Adam(model2.parameters(), lr=learning_rate)\nloss_fn = nn.CrossEntropyLoss()\ntrain(model2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"STEP6- COMPARED THE MODELS BY PERFORMANCE METRICS."},{"metadata":{"trusted":true},"cell_type":"code","source":"#A function to plot confusion matrix.\ndef plot_confusion_matrix(cm, classes,\n                          normalize=True,\n                          title='Confusion matrix',\n                          cmap=plt.cm.Blues):\n    \"\"\"\n    This function prints and plots the confusion matrix.\n    \"\"\"\n    import itertools\n    if normalize:\n        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n        print(\"Normalized confusion matrix\")\n    else:\n        print('Confusion matrix, without normalization')\n    plt.figure(figsize=(20,10))\n\n    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n    plt.title(title)\n    plt.colorbar()\n    tick_marks = np.arange(len(classes))\n    plt.xticks(tick_marks, classes, rotation=45)\n    plt.yticks(tick_marks, classes)\n\n    fmt = '.2f' if normalize else 'd'\n    thresh = cm.max() / 2.\n    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n        plt.text(j, i, format(cm[i, j], fmt),\n                 horizontalalignment=\"center\",\n                 color=\"white\" if cm[i, j] > thresh else \"black\")\n\n    plt.ylabel('True label')\n    plt.xlabel('Predicted label')\n    plt.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#A function used to get PRECISION, RECALL, F1_SCORE and CONFUSION MATRIX.\ndef metrics(model):\n    y_true = []\n    y_pred = []\n    for data in testloader:\n        inputs, labels = data\n        inputs = inputs.to(device)\n        labels = labels.to(device)\n        outputs = model(inputs)\n        _, pred = torch.max(outputs.data, 1)\n        for i in range(len(labels)):\n            y_true.append(classes[labels[i]])\n        for i in range(len(pred)):\n            y_pred.append(classes[pred[i]])\n    f1 = f1_score(y_true, y_pred, average='weighted')\n    precision = precision_score(y_true, y_pred, average='weighted')\n    recall = recall_score(y_true, y_pred, average='weighted')\n    acc = accuracy_score(y_true, y_pred)\n    print(classification_report(y_true, y_pred))\n    print(\"Precision is \", round(precision,2))\n    print(\"Recall is \", round(recall,2))\n    print(\"f1 score is \", round(f1,2))\n    print(\"accuracy score is \", round(acc,2))\n    cm = confusion_matrix(y_true, y_pred, labels = classes)\n    plot_confusion_matrix(cm, classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Performance metrics of model made using transfer learning-\")\nmetrics(model1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Performance metrics of self-made model-\")\nmetrics(model2)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}