{"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 os\nimport zipfile\nimport numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the computation hardware approach: GPU if available, else CPU\nDEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nDEVICE","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Data","metadata":{}},{"cell_type":"code","source":"train_path = \"/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip\"\ntest_path = \"/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip\"\n\nwith zipfile.ZipFile(train_path, 'r') as zipp:\n    zipp.extractall(\"data/\")\n    \nwith zipfile.ZipFile(test_path, 'r') as zipp:\n    zipp.extractall(\"data/\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# list of all paths to train images\ntrain_paths = os.listdir('data/train/')\ntrain_paths = ['data/train/' + i for i in train_paths]\n\n# Split train and validation data\ntrain_paths, val_paths = train_test_split(train_paths, test_size=0.2, shuffle=True, random_state=42)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Train images: {len(train_paths)}')\nprint(f'Validation images: {len(val_paths)}')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset","metadata":{}},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, data, transform=None):\n        self.data = data\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        image = Image.open(self.data[idx]).convert(\"RGB\")\n        \n        if self.transform:\n            image = self.transform(image)\n            \n        if 'dog' in self.data[idx]:\n            label = 1\n        elif 'cat' in self.data[idx]:\n            label = 0\n            \n        return image, label","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Augmentations & DataLoaders","metadata":{}},{"cell_type":"code","source":"from torchvision import transforms\n\ntransform = transforms.Compose([\n    transforms.Resize((200, 200)),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.RandomRotation(degrees=15),\n    transforms.ToTensor(),\n])\n\n# Create Datasets\ntrain_dataset = CustomDataset(data=train_paths, transform=transform)\nval_dataset = CustomDataset(data=val_paths, transform=transform)\n\n# Create DataLoaders\ntrain_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=16, shuffle=True)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display a photo from the dataset\nimage = train_dataset.__getitem__(42)[0]\nplt.axis('off')\nplt.imshow(image.permute(1, 2, 0).cpu().numpy());","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"from torchvision.models import ResNet18_Weights, resnet18\n\nmodel = resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)\nmodel.fc = nn.Linear(model.fc.in_features, 2)\nmodel = model.to(DEVICE)\n\nloss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Training loop","metadata":{}},{"cell_type":"code","source":"epochs = 10\n\nfor epoch in range(epochs):\n    epoch_loss = 0\n    epoch_acc = 0\n    epoch_loss_val = 0\n    epoch_acc_val = 0\n    \n    for iteration, (X_batch, y_batch) in enumerate(train_loader):\n        model.train()\n        optimizer.zero_grad()\n        outputs = model(X_batch.to(DEVICE))\n        \n        loss = loss_fn(outputs, torch.nn.functional.one_hot(y_batch.to(DEVICE), 2).float())\n        loss.backward()\n        optimizer.step()\n\n        acc = ((outputs.argmax(dim=1) == y_batch.to(DEVICE)).float().mean())\n        epoch_acc += acc/len(train_loader)\n        epoch_loss += loss/len(train_loader)\n    \n    print(f'Epoch {epoch + 1}: train_loss = {epoch_loss}, train_acc = {epoch_acc}')\n\n    \n    for iteration, (X_batch, y_batch) in enumerate(val_loader):  \n        model.eval()\n\n        with torch.no_grad():\n            outputs = model(X_batch.to(DEVICE))\n            loss = loss_fn(outputs, torch.nn.functional.one_hot(y_batch.to(DEVICE), 2).float())\n            \n            \n        # calculate accuracy & loss\n        acc = ((outputs.argmax(dim=1) == y_batch.to(DEVICE)).float().mean())\n        epoch_acc_val += acc/len(val_loader)\n        epoch_loss_val += loss/len(val_loader)\n        \n    print(f'Epoch {epoch + 1}: val_loss = {epoch_loss_val}, val_acc = {epoch_acc_val}')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = train_dataset.__getitem__(22)[0]\n\nmodel.eval()\nwith torch.no_grad():\n    out = model(img.unsqueeze(0).to(DEVICE))\n\nprint(f'Prediction: {\"Cat\" if out.argmax().item() == 0 else \"Dog\"}')\n\nplt.axis('off')\nplt.imshow(img.permute(1, 2, 0).cpu().numpy());","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"predictions = np.array([]).astype('int')\n\nfor i in range(12500):\n    img_path = os.path.join('/kaggle/working/data/test', str(i+1)+'.jpg')\n    image = Image.open(img_path).convert(\"RGB\")\n    image = transform(image)\n\n    model.eval()\n    with torch.no_grad():\n        out = model(image.unsqueeze(0).to(DEVICE)).flatten()\n\n    predictions = np.append(predictions, out.argmax().item())","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv')\nsubmission['label'] = predictions\nsubmission.head()\n\n# submission.to_csv('submission.csv')","metadata":{},"execution_count":null,"outputs":[]}]}