{"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 pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport time\nimport random\nimport os\nfrom PIL import Image\n\nimport torch\n\nfrom torch import nn, optim\nfrom torch.functional import F\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import transforms\nfrom torch.autograd import Variable\nfrom tqdm import tqdm","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = '../input/dog-breed-identification/'\nlabels = pd.read_csv(os.path.join(data_dir, 'labels.csv'))\nassert(len(os.listdir(os.path.join(data_dir, 'train'))) == len(labels))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\nle = LabelEncoder()\nlabels.breed = le.fit_transform(labels.breed)\nlabels.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X = labels.id\ny = labels.breed\n\nfrom sklearn.model_selection import train_test_split\n\nX_train, X_valid, y_train, y_valid = train_test_split(X, y,test_size=0.4,  stratify=y)\nX_valid, X_test, y_valid, y_test = train_test_split(X_valid, y_valid, test_size=0.5,stratify=y_valid)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset_Interpreter(Dataset):\n    def __init__(self, data_path, file_names, labels=None, transforms=None):\n        self.data_path = data_path\n        self.file_names = file_names\n        self.labels = labels\n        self.transforms = transforms\n        \n    def __len__(self):\n        return (len(self.file_names))\n    \n    def __getitem__(self, idx):\n        img_name = f'{self.file_names.iloc[idx]}.jpg'\n        full_address = os.path.join(self.data_path, img_name)\n        image = Image.open(full_address)\n        label = self.labels.iloc[idx]\n        \n        if self.transforms is not None:\n            image = self.transforms(image)\n            \n        return np.array(image), label","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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'{le.inverse_transform([images[i][1]])}')\n        ax.imshow(np.array(images[i][0]))\n        ax.axis('off')\n        ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"N_IMAGES = 9\n\ntrain_data = Dataset_Interpreter(data_path=data_dir+'train/', file_names=X_train, labels=y_train)\nimages = [(image, label) for image, label in [train_data[i] for i in range(N_IMAGES)]] \nplot_images(images)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normalize = transforms.Normalize(\n   mean=[0.485, 0.456, 0.406],\n   std=[0.229, 0.224, 0.225]\n)\ntransforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)\ntrain_transforms = transforms.Compose([transforms.Resize(224),\n                               transforms.CenterCrop(224),\n                               transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0),\n                               transforms.RandomHorizontalFlip(p=0.5),\n                               transforms.RandomVerticalFlip(p=0.5),\n                               transforms.RandomGrayscale(p=0.1), \n                               transforms.ToTensor(),\n                               normalize])\ntest_transforms = transforms.Compose([transforms.Resize(224),\n                               transforms.CenterCrop(224),\n                               transforms.ToTensor(),\n                               normalize])\n\ntrain_data = Dataset_Interpreter(data_path=data_dir+'train/', file_names=X_train, labels=y_train, transforms=train_transforms)\nvalid_data = Dataset_Interpreter(data_path=data_dir+'train/', file_names=X_valid, labels=y_valid, transforms=test_transforms)\ntest_data = Dataset_Interpreter(data_path=data_dir+'train/', file_names=X_test, labels=y_test, transforms=test_transforms)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 64\n\ntrain_iterator = DataLoader(train_data, shuffle=True, batch_size= BATCH_SIZE)\nvalid_iterator = DataLoader(valid_data, batch_size=BATCH_SIZE)\ntest_iterator = DataLoader(test_data, batch_size = BATCH_SIZE)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision import models\nmodel = models.resnet34(pretrained=True).cuda()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for name, param in model.named_parameters():\n    if(\"bn\" not in name):\n        param.requires_grad = False","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fc = nn.Linear(model.fc.in_features,120).to(device)\noptimizer = optim.Adam(model.parameters(), lr = 1e-2)\nloss_criterion = nn.CrossEntropyLoss().cuda()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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 tqdm(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)\ndef 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 tqdm(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)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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})","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_stats_ResNet34 = fit_model(model, 'ResNet34', train_iterator, valid_iterator, optimizer, loss_criterion, device, epochs=20)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_training_statistics(train_stats_ResNet34, 'ResNet34')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a = next(iter(test_iterator))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a[0][1].shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"b=a[0][1].permute(1,2,0)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"b.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision.utils import make_grid","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15, 15))\nfor data in test_iterator:\n    (img,mask) = data\n    predict = model(img.cuda())\n    predict = torch.argmax(predict,dim=1)\n    for i in range(9):\n        image = img[i]\n        ax = plt.subplot(3, 3, i + 1)\n        plt.imshow(make_grid(img[i],normalize=True).permute(1,2,0))\n        plt.title('label{}'.format(mask[i].numpy()))\n        plt.xlabel('predict{}'.format(predict[i].numpy())\n        plt.axis(\"on\")\n        plt.tight_layout()\n    break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}