{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\n\nimport pandas as pd\nimport numpy as np\nfrom sklearn.preprocessing import LabelEncoder\nimport matplotlib.pyplot as plt\nimport copy\nimport time\nimport random\nimport os\nfrom PIL import Image\nfrom IPython.display import display\n\nimport torch\nimport torchvision\nfrom torch import nn, optim\nfrom torchvision import models\nfrom torch.functional import F\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import transforms\nfrom torch.autograd import Variable","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.style.use('seaborn-whitegrid')\nplt.rcParams['lines.linewidth'] = 2\nplt.rcParams['font.sans-serif'] = 'Arial'\nplt.rcParams['text.color'] = 'black'\nplt.rcParams['axes.labelcolor']= 'black'\nplt.rcParams['xtick.color'] = 'black'\nplt.rcParams['ytick.color'] = 'black'\nplt.rcParams['font.size']=12","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"SEED = 1234\n\nrandom.seed(SEED)\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)\ntorch.cuda.manual_seed(SEED)\ntorch.backends.cudnn.deterministic = True\n\ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"data_dir = '/kaggle/input/state-farm-distracted-driver-detection/'\nlabels = pd.read_csv(data_dir+'driver_imgs_list.csv')\nsample_sub = pd.read_csv(data_dir+'sample_submission.csv')\n\ndisplay(labels.head())\ndisplay(sample_sub.head())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_img_dir = os.path.join(data_dir, 'imgs/train')\ntest_img_dir = os.path.join(data_dir, 'imgs/test')\n\nnum_training_examples = 0\nfor fol in os.listdir(train_img_dir):\n    num_training_examples += len(os.listdir(os.path.join(train_img_dir, fol)))\n\nassert(num_training_examples == len(labels))\nassert(len(os.listdir(test_img_dir)) == len(sample_sub))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data = torchvision.datasets.ImageFolder(root = train_img_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data[0][0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels.classname.map(train_data.class_to_idx)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_images(images):\n\n    n_images = len(images)\n\n    rows = int(np.sqrt(n_images))\n    cols = int(np.sqrt(n_images))\n\n    fig = plt.figure(figsize=(20,10))\n    for i in range(rows*cols):\n        ax = fig.add_subplot(rows, cols, i+1)\n        ax.set_title(f'{images[i][1]}')\n        ax.imshow(np.array(images[i][0]))\n        ax.axis('off')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"N_IMAGES = 9\n\nimages = [(image, label) for image, label in [train_data[i] for i in range(N_IMAGES)]] \nplot_images(images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"VALID_RATIO = 0.9\n\nn_train_examples = int(len(train_data) * VALID_RATIO)\nn_valid_examples = len(train_data) - n_train_examples\n\ntrain_data, valid_data = torch.utils.data.random_split(train_data, \n                                           [n_train_examples, n_valid_examples])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"normalize = transforms.Normalize(\n   mean=[0.485, 0.456, 0.406],\n   std=[0.229, 0.224, 0.225]\n)\ntrain_transforms = transforms.Compose([transforms.Resize(224),\n                               transforms.CenterCrop(224),\n                               transforms.ToTensor(),\n                               normalize])\ntest_transforms = transforms.Compose([transforms.Resize(224),\n                               transforms.CenterCrop(224),\n                               transforms.ToTensor(),\n                               normalize])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.dataset.transform = train_transforms\nvalid_data = copy.deepcopy(valid_data)\nvalid_data.dataset.transform = test_transforms","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'Number of training examples: {len(train_data)}')\nprint(f'Number of validation examples: {len(valid_data)}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"BATCH_SIZE = 256\n\ntrain_iterator = DataLoader(train_data, \n                                 shuffle = True, \n                                 batch_size = BATCH_SIZE)\n\nvalid_iterator = DataLoader(valid_data, \n                                 batch_size = BATCH_SIZE*2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def count_parameters(model):\n    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n\ndef epoch_time(start_time, end_time):\n    elapsed_time = end_time - start_time\n    elapsed_mins = int(elapsed_time / 60)\n    elapsed_secs = int(elapsed_time - (elapsed_mins * 60))\n    return elapsed_mins, elapsed_secs\n\ndef calculate_accuracy(y_pred, y):\n    top_pred = y_pred.argmax(1, keepdim = True)\n    correct = top_pred.eq(y.view_as(top_pred)).sum()\n    acc = correct.float() / y.shape[0]\n    return acc","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train(model, iterator, optimizer, criterion, device):\n    \n    epoch_loss = 0\n    epoch_acc = 0\n    \n    model.train()\n    \n    for (x, y) in iterator:\n        \n        x = Variable(torch.FloatTensor(np.array(x))).to(device)\n        y = Variable(torch.LongTensor(y)).to(device)\n        \n        optimizer.zero_grad()\n                \n        y_pred = model(x)\n        \n        loss = criterion(y_pred, y)\n        \n        acc = calculate_accuracy(y_pred, y)\n        \n        loss.backward()\n        \n        optimizer.step()\n        \n        epoch_loss += loss.item()\n        epoch_acc += acc.item()\n        \n    return epoch_loss / len(iterator), epoch_acc / len(iterator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def evaluate(model, iterator, criterion, device):\n    \n    epoch_loss = 0\n    epoch_acc = 0\n    \n    model.eval()\n    \n    with torch.no_grad():\n        \n        for (x, y) in iterator:\n\n            x = Variable(torch.FloatTensor(np.array(x))).to(device)\n            y = Variable(torch.LongTensor(y)).to(device)\n        \n            y_pred = model(x)\n\n            loss = criterion(y_pred, y)\n\n            acc = calculate_accuracy(y_pred, y)\n\n            epoch_loss += loss.item()\n            epoch_acc += acc.item()\n        \n    return epoch_loss / len(iterator), epoch_acc / len(iterator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fit_model(model, model_name, train_iterator, valid_iterator, optimizer, loss_criterion, device, epochs):\n    \"\"\" Fits a dataset to model\"\"\"\n    best_valid_loss = float('inf')\n    \n    train_losses = []\n    valid_losses = []\n    train_accs = []\n    valid_accs = []\n    \n    for epoch in range(epochs):\n    \n        start_time = time.time()\n    \n        train_loss, train_acc = train(model, train_iterator, optimizer, loss_criterion, device)\n        valid_loss, valid_acc = evaluate(model, valid_iterator, loss_criterion, device)\n        \n        train_losses.append(train_loss)\n        valid_losses.append(valid_loss)\n        train_accs.append(train_acc*100)\n        valid_accs.append(valid_acc*100)\n    \n        if valid_loss < best_valid_loss:\n            best_valid_loss = valid_loss\n            torch.save(model.state_dict(), f'{model_name}.pt')\n    \n        end_time = time.time()\n\n        epoch_mins, epoch_secs = epoch_time(start_time, end_time)\n    \n        print(f'Epoch: {epoch+1:02} | Epoch Time: {epoch_mins}m {epoch_secs}s')\n        print(f'\\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')\n        print(f'\\t Val. Loss: {valid_loss:.3f} |  Val. Acc: {valid_acc*100:.2f}%')\n        \n    return pd.DataFrame({f'{model_name}_Training_Loss':train_losses, \n                        f'{model_name}_Training_Acc':train_accs, \n                        f'{model_name}_Validation_Loss':valid_losses, \n                        f'{model_name}_Validation_Acc':valid_accs})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_training_statistics(train_stats, model_name):\n    \n    fig, axes = plt.subplots(2, figsize=(15,15))\n    axes[0].plot(train_stats[f'{model_name}_Training_Loss'], label=f'{model_name}_Training_Loss')\n    axes[0].plot(train_stats[f'{model_name}_Validation_Loss'], label=f'{model_name}_Validation_Loss')\n    axes[1].plot(train_stats[f'{model_name}_Training_Acc'], label=f'{model_name}_Training_Acc')\n    axes[1].plot(train_stats[f'{model_name}_Validation_Acc'], label=f'{model_name}_Validation_Acc')\n    \n    axes[0].set_xlabel(\"Number of Epochs\"), axes[0].set_ylabel(\"Loss\")\n    axes[1].set_xlabel(\"Number of Epochs\"), axes[1].set_ylabel(\"Accuracy in %\")\n    \n    axes[0].legend(), axes[1].legend()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = models.resnet18(pretrained=True)\nprint(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for name, param in model.named_parameters():\n    if(\"bn\" not in name):\n        param.requires_grad = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.fc = nn.Linear(model.fc.in_features,10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model= model.to(device)\nloss_criterion = nn.CrossEntropyLoss().to(device)\noptimizer = optim.Adam(model.parameters(), lr = 1e-2)\n\nprint(f'The model has {count_parameters(model):,} trainable parameters')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_stats_ResNet18 = fit_model(model, 'ResNet18', train_iterator, valid_iterator, optimizer, loss_criterion, device, epochs=2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_training_statistics(train_stats_ResNet18, 'ResNet18')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}