{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-09-20T13:39:42.090835Z","iopub.execute_input":"2023-09-20T13:39:42.091530Z","iopub.status.idle":"2023-09-20T13:39:42.447382Z","shell.execute_reply.started":"2023-09-20T13:39:42.091498Z","shell.execute_reply":"2023-09-20T13:39:42.446451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\n\nimport matplotlib.pyplot as plt\nimport torch \nimport torch.nn as nn\nfrom torchvision import models, transforms, datasets\nimport random\nimport zipfile\nfrom torch import optim\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:39:42.450880Z","iopub.execute_input":"2023-09-20T13:39:42.451286Z","iopub.status.idle":"2023-09-20T13:39:46.423621Z","shell.execute_reply.started":"2023-09-20T13:39:42.451258Z","shell.execute_reply":"2023-09-20T13:39:46.422613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 0: Prepare the dataset","metadata":{}},{"cell_type":"code","source":"with zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', 'r') as train_zip:\n    train_zip.extractall('.')  \nimage_dir = \"../working/train/\"\nfilenames = os.listdir(image_dir)\nlabels = [x.split(\".\")[0] for x in filenames]\ndf = pd.DataFrame({\"filename\": filenames, \"label\": labels})\ndf.head()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-09-20T13:39:46.427350Z","iopub.execute_input":"2023-09-20T13:39:46.427760Z","iopub.status.idle":"2023-09-20T13:39:58.246849Z","shell.execute_reply.started":"2023-09-20T13:39:46.427733Z","shell.execute_reply":"2023-09-20T13:39:58.245881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"grouped_data = df.groupby(\"label\")\n\nnum_images_per_category = 5\n\nfig, axes = plt.subplots(len(grouped_data), num_images_per_category, figsize=(20, 20))\n\nfor i, (category, group) in enumerate(grouped_data):\n  \n    random_indices = random.sample(range(len(group)), num_images_per_category)\n\n    for j, index in enumerate(random_indices):\n        filename = group.iloc[index][\"filename\"]\n        label = group.iloc[index][\"label\"]\n        image_path = os.path.join(image_dir, filename)\n        image = Image.open(image_path)\n\n        axes[i, j].imshow(image)\n        axes[i, j].set_title(\"Label: \" + label, fontsize = 30)\n        \n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:39:58.293342Z","iopub.execute_input":"2023-09-20T13:39:58.294288Z","iopub.status.idle":"2023-09-20T13:40:05.708028Z","shell.execute_reply.started":"2023-09-20T13:39:58.294251Z","shell.execute_reply":"2023-09-20T13:40:05.706854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 1: Load Pretrained DenseNet121","metadata":{}},{"cell_type":"code","source":"model = models.densenet121(pretrained=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:05.709351Z","iopub.execute_input":"2023-09-20T13:40:05.709781Z","iopub.status.idle":"2023-09-20T13:40:06.759340Z","shell.execute_reply.started":"2023-09-20T13:40:05.709736Z","shell.execute_reply":"2023-09-20T13:40:06.758300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 2: Modify Output Layer","metadata":{}},{"cell_type":"code","source":"num_classes = 2\n\nfrom collections import OrderedDict\nclassifier = nn.Sequential(OrderedDict([\n                          ('fc1', nn.Linear(1024, 500)),\n                          ('relu', nn.ReLU()),\n                          ('fc2', nn.Linear(500, 2)),\n                          ('output', nn.LogSoftmax(dim=1))\n                          ]))\n\nmodel.classifier = classifier\n#model.classifier = nn.Linear(model.classifier.in_features, num_classes)","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:06.760945Z","iopub.execute_input":"2023-09-20T13:40:06.761621Z","iopub.status.idle":"2023-09-20T13:40:06.776466Z","shell.execute_reply.started":"2023-09-20T13:40:06.761587Z","shell.execute_reply":"2023-09-20T13:40:06.775403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 3: Freeze Feature Extractor","metadata":{}},{"cell_type":"code","source":"for param in model.features.parameters():\n    param.requires_grad = False","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:06.778291Z","iopub.execute_input":"2023-09-20T13:40:06.778966Z","iopub.status.idle":"2023-09-20T13:40:06.786286Z","shell.execute_reply.started":"2023-09-20T13:40:06.778909Z","shell.execute_reply":"2023-09-20T13:40:06.785097Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Step extra: Move Model to GPU\n# model = model.to('cuda')  ","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:06.792330Z","iopub.execute_input":"2023-09-20T13:40:06.792715Z","iopub.status.idle":"2023-09-20T13:40:06.799962Z","shell.execute_reply.started":"2023-09-20T13:40:06.792683Z","shell.execute_reply":"2023-09-20T13:40:06.798876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 4: Define Loss and Optimizer and Transform","metadata":{}},{"cell_type":"code","source":"criterion= nn.NLLLoss()\n#criterion = nn.CrossEntropyLoss()\n\noptimizer=optim.Adam(model.classifier.parameters(),lr=0.001)\n#optimizer = torch.optim.SGD(model.classifier.parameters(), lr=0.001)\n\nmean = [0.485, 0.456, 0.406]\nstd = [0.229, 0.224, 0.225]\n\ntrain_transforms = transforms.Compose([\n                                        transforms.Resize((224, 224)),  # Resize the image to 224x224\n                                        transforms.ToTensor(),         # Convert the image to a PyTorch tensor\n                                        transforms.Normalize(mean, std)  # Normalize with specified mean and std\n                                        ])\n\ntest_transforms = transforms.Compose([\n                                        transforms.Resize((224, 224)),  # Resize the image to 224x224\n                                        transforms.ToTensor(),         # Convert the image to a PyTorch tensor\n                                        transforms.Normalize(mean, std)  # Normalize with specified mean and std\n                                        ])","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:06.804600Z","iopub.execute_input":"2023-09-20T13:40:06.804947Z","iopub.status.idle":"2023-09-20T13:40:06.818396Z","shell.execute_reply.started":"2023-09-20T13:40:06.804896Z","shell.execute_reply":"2023-09-20T13:40:06.817377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 5: Data Loading and Preprocessing","metadata":{}},{"cell_type":"code","source":"import zipfile\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/train/')\n\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/test1.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/test/')","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:06.823316Z","iopub.execute_input":"2023-09-20T13:40:06.823830Z","iopub.status.idle":"2023-09-20T13:40:21.288246Z","shell.execute_reply.started":"2023-09-20T13:40:06.823628Z","shell.execute_reply":"2023-09-20T13:40:21.287102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = datasets.ImageFolder(root='/kaggle/working/train/', transform=train_transforms)\ntest_data = datasets.ImageFolder(root='/kaggle/working/test/', transform=test_transforms)\n\n# DataLoader\ntrainloader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True)\ntestloader = torch.utils.data.DataLoader(test_data, batch_size=32, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:21.289612Z","iopub.execute_input":"2023-09-20T13:40:21.289978Z","iopub.status.idle":"2023-09-20T13:40:21.525189Z","shell.execute_reply.started":"2023-09-20T13:40:21.289943Z","shell.execute_reply":"2023-09-20T13:40:21.524176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Step 6: Training Loop and Validation for each Epoch on Testing Data","metadata":{}},{"cell_type":"code","source":"num_epochs = 2\nprint_every = 10\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    for i, (inputs, labels) in enumerate(trainloader, 1):\n        optimizer.zero_grad()\n        #inputs, labels = inputs.to('cuda'), labels.to('cuda')  # Move data to GPU\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n\n        if i % print_every == 0:\n            print(f\"Epoch: {epoch+1}/{num_epochs}, Batch: {i}/{len(trainloader)}, Loss: {running_loss/print_every:.7f}\")\n            running_loss = 0.0\n    \n    # Validation\n    model.eval()\n    test_loss = 0.0\n    accuracy = 0\n    with torch.no_grad():\n        for inputs, labels in testloader:\n            #inputs, labels = inputs.to('cuda'), labels.to('cuda')  # Move data to GPU\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            test_loss += loss.item()\n            ps = torch.exp(outputs)\n            top_p, top_class = ps.topk(1, dim=1)\n            equals = top_class == labels.view(*top_class.shape)\n            accuracy += torch.mean(equals.type(torch.FloatTensor))\n\n    print(f\"Epoch: {epoch+1}/{num_epochs}.. \"\n          f\"Training Loss: {running_loss/print_every:.3f}.. \"\n          f\"Test Loss: {test_loss/len(testloader):.3f}.. \"\n          f\"Test Accuracy: {accuracy/len(testloader):.3f}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-20T13:40:21.526508Z","iopub.execute_input":"2023-09-20T13:40:21.526858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}