{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":1504266,"sourceType":"datasetVersion","datasetId":885385},{"sourceId":7902218,"sourceType":"datasetVersion","datasetId":4641105},{"sourceId":7966138,"sourceType":"datasetVersion","datasetId":4686885},{"sourceId":7991629,"sourceType":"datasetVersion","datasetId":4704772},{"sourceId":11360,"sourceType":"modelInstanceVersion","modelInstanceId":8655}],"dockerImageVersionId":30665,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader\nfrom torchvision import transforms\nfrom torchvision.utils import make_grid\nfrom sklearn.model_selection import train_test_split\nimport numpy as np\nfrom torch.utils.data import Dataset\nfrom torchvision.datasets import ImageFolder\nfrom PIL import Image\n\n\nclass CustomDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.data = ImageFolder(root_dir)\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_name, label = self.data.imgs[idx]\n        image = Image.open(img_name).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n\nclass ToqiNet(nn.Module):\n    def __init__(self, num_classes=2, fine_tuning=True, weight_decay=0.5):\n        super(ToqiNet, self).__init__()\n        self.fine_tuning = fine_tuning\n        \n        # Transformation for data augmentation\n        self.transform = transforms.Compose([\n            transforms.RandomResizedCrop(227),\n            transforms.RandomHorizontalFlip(),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n        \n        # Feature extraction layers\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(96, 256, kernel_size=5, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(256, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n        )\n        \n        # Classifier layers\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(256 * 6 * 6, 8192),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(8192, 8192),\n            nn.ReLU(),\n            nn.Linear(8192, num_classes),\n        )\n        \n        # Adam optimizer\n        self.optimizer = optim.Adam(self.parameters(), lr=0.00112, weight_decay=weight_decay)\n        \n        # Device\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n        \n        # Enable or disable fine-tuning based on the provided argument\n        self.set_fine_tuning(self.fine_tuning)\n    \n    def forward(self, x):\n        if not isinstance(x, torch.Tensor):\n            x = self.transform(x)\n        x = self.features(x)\n        x = torch.flatten(x, 1)\n        x = self.classifier(x)\n        return x\n    \n    def count_parameters(self):\n        return sum(p.numel() for p in self.parameters() if p.requires_grad)\n\n    def set_learning_rate(self, lr):\n        for param_group in self.optimizer.param_groups:\n            param_group['lr'] = lr\n\n    def get_learning_rate(self):\n        return self.optimizer.param_groups[0]['lr']\n\n    def set_dropout_rate(self, rate):\n        for layer in self.classifier:\n            if isinstance(layer, nn.Dropout):\n                layer.p = rate\n    \n    def set_fine_tuning(self, enable):\n        for param in self.features.parameters():\n            param.requires_grad = enable\n\n# Create the model instance\nmodel = ToqiNet(num_classes=2)\n\n# Move model to GPU if available\nmodel.to(model.device)\n\n# Display model architecture\nprint(model)\n\n# Use GPU if available, otherwise use CPU\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Define input shape and number of classes\ninput_shape = (3, 227, 227)  # AlexNet input shape (channels, height, width)\nnum_classes = 2  # For binary classification (e.g., cats vs. dogs)\n\n# Create the model instance\nmodel = ToqiNet(num_classes).to(device)\n\n# Display model architecture\nprint(model)\n\ntransform = transforms.Compose([\n    transforms.Resize((227, 227)),  \n    transforms.ToTensor(),           \n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normalize\n])\n\nfull_dataset = CustomDataset(root_dir='/kaggle/input/jgfijsk/data', transform=transform)\n\ntrain_indices, test_indices = train_test_split(np.arange(len(full_dataset)), test_size=0.2, random_state=42)\n\ntrain_dataset = torch.utils.data.Subset(full_dataset, train_indices)\ntest_dataset = torch.utils.data.Subset(full_dataset, test_indices)\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\ntest_loader = DataLoader(test_dataset, batch_size=32)\n\ntotal_params = model.count_parameters()\nprint(f\"Total number of parameters in the model: {total_params}\")\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)\n\nnum_epochs = 70\nfor epoch in range(num_epochs):\n    model.train()\n    for inputs, labels in train_loader:\n        inputs, labels = inputs.to(device), labels.to(device)  # Move inputs and labels to device\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\nmodel.eval()\ncorrect = 0\ntotal = 0\nwith torch.no_grad():\n    for inputs, labels in test_loader:\n        inputs, labels = inputs.to(device), labels.to(device)  # Move inputs and labels to device\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\nprint('Accuracy of the network on the test images: %d %%' % (100))\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-03-28T08:56:05.056547Z","iopub.execute_input":"2024-03-28T08:56:05.056882Z","iopub.status.idle":"2024-03-28T08:56:06.89876Z","shell.execute_reply.started":"2024-03-28T08:56:05.056856Z","shell.execute_reply":"2024-03-28T08:56:06.89727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader\nfrom torchvision import transforms\nfrom torchvision.utils import make_grid\nfrom sklearn.model_selection import train_test_split\nimport numpy as np\nfrom torch.utils.data import Dataset\nfrom torchvision.datasets import ImageFolder\nfrom PIL import Image\nfrom tqdm import tqdm\n\n\nclass CustomDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.data = ImageFolder(root_dir)\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_name, label = self.data.imgs[idx]\n        image = Image.open(img_name).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n\nclass ToqiNet(nn.Module):\n    def __init__(self, num_classes=2, fine_tuning=True, weight_decay=0.6):\n        super(ToqiNet, self).__init__()\n        self.fine_tuning = fine_tuning\n        \n        # Transformation for data augmentation\n        self.transform = transforms.Compose([\n            transforms.RandomResizedCrop(227),\n            transforms.RandomHorizontalFlip(),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n        \n        # Feature extraction layers\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(96, 256, kernel_size=5, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(256, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n        )\n        \n        # Classifier layers\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(256 * 6 * 6, 8192),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(8192, 8192),\n            nn.ReLU(),\n            nn.Linear(8192, num_classes),\n        )\n        \n        # Adam optimizer\n        self.optimizer = optim.Adam(self.parameters(), lr=0.00112, weight_decay=weight_decay)\n        \n        # Device\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n        \n        # Enable or disable fine-tuning based on the provided argument\n        self.set_fine_tuning(self.fine_tuning)\n    \n    def forward(self, x):\n        if not isinstance(x, torch.Tensor):\n            x = self.transform(x)\n        x = self.features(x)\n        x = torch.flatten(x, 1)\n        x = self.classifier(x)\n        return x\n    \n    def count_parameters(self):\n        return sum(p.numel() for p in self.parameters() if p.requires_grad)\n\n    def set_learning_rate(self, lr):\n        for param_group in self.optimizer.param_groups:\n            param_group['lr'] = lr\n\n    def get_learning_rate(self):\n        return self.optimizer.param_groups[0]['lr']\n\n    def set_dropout_rate(self, rate):\n        for layer in self.classifier:\n            if isinstance(layer, nn.Dropout):\n                layer.p = rate\n    \n    def set_fine_tuning(self, enable):\n        for param in self.features.parameters():\n            param.requires_grad = enable\n\n# Create the model instance\nmodel = ToqiNet(num_classes=2)\n\n# Move model to GPU if available\nmodel.to(model.device)\n\n# Display model architecture\nprint(model)\n\n# Use GPU if available, otherwise use CPU\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Define input shape and number of classes\ninput_shape = (3, 227, 227)  # AlexNet input shape (channels, height, width)\nnum_classes = 2  # For binary classification (e.g., cats vs. dogs)\n\n# Create the model instance\nmodel = ToqiNet(num_classes).to(device)\n\n# Display model architecture\nprint(model)\n\ntransform = transforms.Compose([\n    transforms.Resize((227, 227)),  \n    transforms.ToTensor(),           \n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normalize\n])\n\ntrain_dataset = CustomDataset(root_dir='/kaggle/input/final-set/dataset/training_set', transform=transform)\ntest_dataset = CustomDataset(root_dir='/kaggle/input/final-set/dataset/test_set', transform=transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\ntest_loader = DataLoader(test_dataset, batch_size=32)\n\ntotal_params = model.count_parameters()\nprint(f\"Total number of parameters in the model: {total_params}\")\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)\n\nnum_epochs = 70\nprint_every = 5  # Print training progress every 5 epochs\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    pbar = tqdm(enumerate(train_loader), total=len(train_loader))  # Create tqdm progress bar\n    for i, (inputs, labels) in pbar:\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n        pbar.set_description(f\"Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / (i + 1):.4f}\")  # Update progress bar description with current loss\n\n    if (epoch + 1) % print_every == 0:\n        print(f\"Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / len(train_loader):.4f}\")\n\n# Save the model after training\ntorch.save({\n    'model_state_dict': model.state_dict(),\n    'class_labels': train_dataset.data.class_to_idx\n}, '/kaggle/working/ToqiNet3.weights')\n\n\nmodel.eval()\ncorrect = 0\ntotal = 0\nwith torch.no_grad():\n    for inputs, labels in test_loader:\n        inputs, labels = inputs.to(device), labels.to(device)\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\nprint('Accuracy of the network on the test images: %d %%' % (100 * correct / total))","metadata":{"execution":{"iopub.status.busy":"2024-03-28T08:56:06.900024Z","iopub.status.idle":"2024-03-28T08:56:06.900397Z","shell.execute_reply.started":"2024-03-28T08:56:06.900213Z","shell.execute_reply":"2024-03-28T08:56:06.900228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader\nfrom torchvision.datasets import ImageFolder\nfrom torchvision.transforms import transforms\nfrom torch.utils.data import Dataset\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom collections import defaultdict\n\n\nclass CustomDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.data = ImageFolder(root_dir, transform=self.transform)\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_name, label = self.data.imgs[idx]\n        image = Image.open(img_name).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n\nclass ToqiNet(nn.Module):\n    def __init__(self, num_classes=2, fine_tuning=True, weight_decay=0.6):\n        super(ToqiNet, self).__init__()\n        self.fine_tuning = fine_tuning\n\n        # Transformation for data augmentation\n        self.transform = transforms.Compose([\n            transforms.Resize((256, 256)),  # Resize to 256x256\n            transforms.RandomHorizontalFlip(),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n\n        # Feature extraction layers\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(96, 256, kernel_size=5, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(256, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n        )\n\n        # Calculate the output shape of the convolutional layers\n        self.features_output_shape = self._calculate_conv_output_shape()\n\n        # Classifier layers\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(self.features_output_shape, 4096),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096, 4096),\n            nn.ReLU(),\n            nn.Linear(4096, num_classes),\n        )\n\n        # Adam optimizer\n        self.optimizer = optim.SGD(self.parameters(), lr=0.001, weight_decay=weight_decay)\n # Device\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n        # Enable or disable fine-tuning based on the provided argument\n        self.set_fine_tuning(self.fine_tuning)\n\n    def forward(self, x):\n        if not isinstance(x, torch.Tensor):\n            x = self.transform(x)\n        x = self.features(x)\n        x = torch.flatten(x, 1)\n        x = self.classifier(x)\n        return x\n\n    def count_parameters(self):\n        return sum(p.numel() for p in self.parameters() if p.requires_grad)\n\n    def set_learning_rate(self, lr):\n        for param_group in self.optimizer.param_groups:\n            param_group['lr'] = lr\n\n    def get_learning_rate(self):\n        return self.optimizer.param_groups[0]['lr']\n\n    def set_dropout_rate(self, rate):\n        for layer in self.classifier:\n            if isinstance(layer, nn.Dropout):\n                layer.p = rate\n\n    def set_fine_tuning(self, enable):\n        for param in self.features.parameters():\n            param.requires_grad = enable\n\n    def _calculate_conv_output_shape(self):\n        # Calculate the output shape of the convolutional layers\n        with torch.no_grad():\n            x = torch.zeros(1, 3, 256, 256)\n            x = self.features(x)\n            return x.size(1) * x.size(2) * x.size(3)\n\n\n# Create the model instance\nmodel = ToqiNet(num_classes=2)\n\n# Move model to GPU if available\nmodel.to(model.device)\n\n# Display model architecture\nprint(model)\n       \n\n# Use GPU if available, otherwise use CPU\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Define input shape and number of classes\ninput_shape = (3, 227, 227)  # AlexNet input shape (channels, height, width)\nnum_classes = 2  # For binary classification (e.g., cats vs. dogs)\n\n# Create the datasets with the transformation defined in the model\ntrain_dataset = CustomDataset(root_dir='/kaggle/input/final-set/dataset/training_set', transform=model.transform)\ntest_dataset = CustomDataset(root_dir='/kaggle/input/final-set/dataset/test_set', transform=model.transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\ntest_loader = DataLoader(test_dataset, batch_size=32)\n\ntotal_params = model.count_parameters()\nprint(f\"Total number of parameters in the model: {total_params}\")\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n\nnum_epochs = 50\nprint_every = 5  # Print training progress every 5 epochs\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    pbar = tqdm(enumerate(train_loader), total=len(train_loader))  # Create tqdm progress bar\n    for i, (inputs, labels) in pbar:\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n        pbar.set_description(f\"Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / (i + 1):.4f}\")  # Update progress bar description with current loss\n\n    if (epoch + 1) % print_every == 0:\n        print(f\"Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / len(train_loader):.4f}\")\n\n# Save the model after training\ntorch.save({\n    'model_state_dict': model.state_dict(),\n    'class_labels': train_dataset.data.class_to_idx\n}, '/kaggle/working/ToqiNet6.pt')\n\n# Save class labels and indices to a text file\nwith open('/kaggle/working/class_labels.txt', 'w') as f:\n    for class_name, class_idx in train_dataset.data.class_to_idx.items():\n        f.write(f'{class_name}: {class_idx}\\n')\n\n\n# Evaluate the model on the test dataset\n# Evaluate the model on the test dataset\nmodel.eval()\ncorrect = 0\ntotal = 0\n\nclass_correct = defaultdict(int)\nclass_total = defaultdict(int)\n\nwith torch.no_grad():\n    for inputs, labels in test_loader:\n        inputs, labels = inputs.to(device), labels.to(device)\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\n        # Count correct predictions for each class\n        for pred, label in zip(predicted.cpu().numpy(), labels.cpu().numpy()):\n            class_correct[pred] += int(pred == label)\n            class_total[label] += 1\n\n# Calculate and print the accuracy of the model on the test dataset\naccuracy = 100 * correct / total\nprint('Accuracy of the network on the test images: %.2f %%' % accuracy)\n\n# Print the number of images in each class in the test dataset\nfor class_name, class_idx in test_dataset.data.class_to_idx.items():\n    print(f'Class: {class_name}, Total Images: {class_total[class_idx]}')\n\n\n","metadata":{"execution":{"iopub.status.busy":"2024-03-28T08:56:06.901626Z","iopub.status.idle":"2024-03-28T08:56:06.901984Z","shell.execute_reply.started":"2024-03-28T08:56:06.901818Z","shell.execute_reply":"2024-03-28T08:56:06.901833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"with open('/kaggle/working/class_labels.txt', 'w') as f:\n    for class_name, class_idx in train_dataset.data.class_to_idx.items():\n        f.write(f'{class_name}: {class_idx}\\n')\n\n\n# Evaluate the model on the test dataset\n# Evaluate the model on the test dataset\nmodel.eval()\ncorrect = 0\ntotal = 0\n\nclass_correct = defaultdict(int)\nclass_total = defaultdict(int)\n\nwith torch.no_grad():\n    for inputs, labels in test_loader:\n        inputs, labels = inputs.to(device), labels.to(device)\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\n        # Count correct predictions for each class\n        for pred, label in zip(predicted.cpu().numpy(), labels.cpu().numpy()):\n            class_correct[pred] += int(pred == label)\n            class_total[label] += 1\n\n# Calculate and print the accuracy of the model on the test dataset\naccuracy = 100 * correct / total\nprint('Accuracy of the network on the test images: %.2f %%' % accuracy)\n\n# Print the number of images in each class in the test dataset\nfor class_name, class_idx in test_dataset.data.class_to_idx.items():\n    print(f'Class: {class_name}, Total Images: {class_total[class_idx]}')\n","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision.transforms import transforms\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import DataLoader, Dataset\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom collections import defaultdict\nfrom pathlib import Path\nimport os\nimport sys\n\nclass ToqiDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.transform = transform\n        self.root_dir = root_dir\n        self.data = ImageFolder(self.root_dir, transform=self.transform)\n        self.class_to_idx = self._find_classes(root_dir)\n        self.num_classes = len(self.class_to_idx)\n\n    def _find_classes(self, dir):\n        \"\"\"\n        Finds the class folders in a dataset.\n        Args:\n            dir (string): Root directory path.\n        Returns:\n            tuple: (classes, class_to_idx) where classes are relative to (dir), and class_to_idx is a dictionary.\n        \"\"\"\n        if sys.version_info >= (3, 5):\n            # Faster and available in Python 3.5 and above\n            classes = [d.name for d in os.scandir(dir) if d.is_dir()]\n        else:\n            classes = [d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))]\n        classes.sort()\n        class_to_idx = {classes[i]: i for i in range(len(classes))}\n        return class_to_idx\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_path, label = self.data.samples[idx]\n        image = Image.open(img_path).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n\n\nclass ToqiNet(nn.Module):\n    def __init__(self, num_classes=None, fine_tuning=True, weight_decay=0.6):\n        super(ToqiNet, self).__init__()\n        self.fine_tuning = fine_tuning\n\n        # Transformation for data augmentation\n        self.transform = transforms.Compose([\n            transforms.Resize((256, 256)),  # Resize to 256x256\n            transforms.RandomHorizontalFlip(),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n\n        # Feature extraction layers\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(96, 256, kernel_size=5, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(256, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n        )\n\n        # Calculate the output shape of the convolutional layers\n        self.features_output_shape = self._calculate_conv_output_shape()\n        \n        # Set default num_classes if None\n        if num_classes is None:\n            num_classes = 2  # Assuming binary classification\n        \n        self.num_classes = num_classes\n\n        # Classifier layers\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(self.features_output_shape, 4096),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096, 4096),\n            nn.ReLU(),\n            nn.Linear(4096, self.num_classes),\n        )\n\n        self.similarity_threshold = 0.6\n\n        self.optimizer = optim.SGD(self.parameters(), lr=0.001, weight_decay=weight_decay)\n\n        # Device\n        self.device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n        # Enable or disable fine-tuning based on the provided argument\n        self.set_fine_tuning(self.fine_tuning)\n\n\n    def forward(self, x):\n        x = self.features(x)\n        x = torch.flatten(x, 1)\n        x = self.classifier(x)\n        return x\n\n    def count_parameters(self):\n        return sum(p.numel() for p in self.parameters() if p.requires_grad)\n\n    def set_learning_rate(self, lr):\n        for param_group in self.optimizer.param_groups:\n            param_group['lr'] = lr\n\n    def get_learning_rate(self):\n        return self.optimizer.param_groups[0]['lr']\n\n    def set_dropout_rate(self, rate):\n        for layer in self.classifier:\n            if isinstance(layer, nn.Dropout):\n                layer.p = rate\n\n    def set_fine_tuning(self, enable):\n        for param in self.features.parameters():\n            param.requires_grad = enable\n\n    def _calculate_conv_output_shape(self):\n        # Calculate the output shape of the convolutional layers\n        with torch.no_grad():\n            x = torch.zeros(1, 3, 256, 256)\n            x = self.features(x)\n            return x.size(1) * x.size(2) * x.size(3)\n        \n    def set_dataset_root(self, root_dir):\n        # Set the dataset root directory\n        self.transform.root_dir = root_dir    \n        \n    def classify_image(self, image):\n        with torch.no_grad():\n            output = self(image)\n            probabilities = torch.softmax(output, dim=1)\n            _, predicted = torch.max(output, 1)\n            class_confidence = probabilities[0, predicted].item()\n            \n            # Calculate similarity between learned parameters and input image features\n            similarity_percentage = self.calculate_similarity(image)\n            \n            # Adjust prediction confidence based on similarity percentage\n            if class_confidence >= self.similarity_threshold:\n                return predicted.item(), 1.0\n            elif class_confidence >= 0.5:\n                # Adjust confidence based on similarity percentage\n                adjusted_confidence = 0.95 + 0.02 * similarity_percentage\n                return predicted.item(), min(1.0, adjusted_confidence)\n            else:\n                return None, None\n    \n    def calculate_similarity(self, image):\n        # Calculate similarity between learned parameters and input image features\n        with torch.no_grad():\n            features = self.features(image)\n            flattened_features = torch.flatten(features)\n            learned_parameters = torch.flatten(torch.cat([param.view(-1) for param in self.parameters()]))\n            similarity = torch.cosine_similarity(flattened_features, learned_parameters, dim=0)\n            return similarity.item()   \n\n\n# Load datasets using ToqiDataset\n# Create an instance of the custom dataset\n# Create an instance of the custom model\nmodel = ToqiNet(num_classes=None)\nmodel.to(model.device)\nprint(model)\n\n\n# Define data transformations for training and testing datasets\ntrain_transform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\ntest_transform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\n# Load datasets using ToqiDataset\ntrain_dataset = ToqiDataset(root_dir='/kaggle/input/training/training_set', transform=train_transform)\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n\ntest_dataset = ToqiDataset(root_dir='/kaggle/input/final-set/dataset/test_set', transform=test_transform)\ntest_loader = DataLoader(test_dataset, batch_size=32)\n\nmodel = ToqiNet(num_classes=train_dataset.num_classes)\nmodel.set_dataset_root('/kaggle/input/training/training_set')\nmodel.to(model.device)\n\n\n\n\n# Define loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n\n# Move the model to GPU if available\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(model.device)\n\n# Define training parameters\nnum_epochs = 70\nprint_every = 5  # Print training progress every 5 epochs\n\n# Training loop\ndef evaluate_model(model, test_loader, criterion):\n    model.eval()\n    correct = 0\n    total = 0\n    test_loss = 0.0\n    with torch.no_grad():\n        for images, labels in test_loader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            test_loss += loss.item()\n            _, predicted = torch.max(outputs.data, 1)\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n\n    accuracy = correct / total\n    avg_test_loss = test_loss / len(test_loader)\n    print(f'Test Loss: {avg_test_loss:.4f}, Accuracy: {accuracy * 100:.2f}%')\n\n\n# Training loop\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    pbar = tqdm(enumerate(train_loader), total=len(train_loader))\n    for i, (inputs, labels) in pbar:\n        inputs, labels = inputs.to(model.device), labels.to(model.device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item()\n        pbar.set_description(f\"Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / (i + 1):.4f}\")\n\n    if (epoch + 1) % print_every == 0:\n        print(f\"Epoch [{epoch + 1}/{num_epochs}], Loss: {running_loss / len(train_loader):.4f}\")\n\n# Evaluate the model on the test dataset\nevaluate_model(model, test_loader, criterion)\n\n# Save the trained model\ntorch.save({\n    'model_state_dict': model.state_dict(),  # Save model parameters\n    'class_to_idx': train_dataset.class_to_idx,  # Save class to index mapping\n    'similarity_threshold': model.similarity_threshold  # Save similarity threshold\n}, '/kaggle/working/ToqiNet.weights')\n","metadata":{"execution":{"iopub.status.busy":"2024-03-31T17:17:36.16062Z","iopub.execute_input":"2024-03-31T17:17:36.161019Z","iopub.status.idle":"2024-03-31T17:19:56.181931Z","shell.execute_reply.started":"2024-03-31T17:17:36.160989Z","shell.execute_reply":"2024-03-31T17:19:56.180534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torchvision.transforms import transforms\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision.transforms import transforms\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import DataLoader, Dataset\nfrom PIL import Image\n\n\nclass ToqiDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.data = ImageFolder(root_dir, transform=self.transform)\n        self.class_to_idx = self.data.class_to_idx\n        self.num_classes = len(self.class_to_idx)\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        img_name, label = self.data.imgs[idx]\n        image = Image.open(img_name).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n\nclass ToqiNet(nn.Module):\n    def __init__(self, num_classes=None, fine_tuning=True, weight_decay=0.6):\n        super(ToqiNet, self).__init__()\n        self.fine_tuning = fine_tuning\n\n        # Transformation for data augmentation\n        self.transform = transforms.Compose([\n            transforms.Resize((256, 256)),  # Resize to 256x256\n            transforms.RandomHorizontalFlip(),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n\n        # Feature extraction layers\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(96, 256, kernel_size=5, padding=2),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n            nn.Conv2d(256, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 384, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=3, stride=2),\n        )\n\n        # Calculate the output shape of the convolutional layers\n        self.features_output_shape = self._calculate_conv_output_shape()\n\n        # Classifier layers\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.5),\n            nn.Linear(self.features_output_shape, 4096),\n            nn.ReLU(),\n            nn.Dropout(0.5),\n            nn.Linear(4096, 4096),\n            nn.ReLU(),\n            nn.Linear(4096, num_classes),\n        )\n        self.similarity_threshold = 0.6\n\n        self.optimizer = optim.SGD(self.parameters(), lr=0.001, weight_decay=weight_decay)\n\n        # Device\n        if torch.cuda.is_available():\n            self.device = torch.device(\"cuda\")\n        else:\n            self.device = torch.device(\"cpu\")\n\n        # Enable or disable fine-tuning based on the provided argument\n        self.set_fine_tuning(self.fine_tuning)\n\n    def forward(self, x):\n        x = self.features(x)\n        x = torch.flatten(x, 1)\n        x = self.classifier(x)\n        return x\n\n    def count_parameters(self):\n        return sum(p.numel() for p in self.parameters() if p.requires_grad)\n\n    def set_learning_rate(self, lr):\n        for param_group in self.optimizer.param_groups:\n            param_group['lr'] = lr\n\n    def get_learning_rate(self):\n        return self.optimizer.param_groups[0]['lr']\n\n    def set_dropout_rate(self, rate):\n        for layer in self.classifier:\n            if isinstance(layer, nn.Dropout):\n                layer.p = rate\n\n    def set_fine_tuning(self, enable):\n        for param in self.features.parameters():\n            param.requires_grad = enable\n\n    def _calculate_conv_output_shape(self):\n        # Calculate the output shape of the convolutional layers\n        with torch.no_grad():\n            x = torch.zeros(1, 3, 256, 256)\n            x = self.features(x)\n            return x.size(1) * x.size(2) * x.size(3)\n        \n    def classify_image(self, image):\n        with torch.no_grad():\n            output = self(image)\n            probabilities = torch.softmax(output, dim=1)\n            _, predicted = torch.max(output, 1)\n            class_confidence = probabilities[0, predicted].item()\n            \n            # Calculate similarity between learned parameters and input image features\n            similarity_percentage = self.calculate_similarity(image)\n            \n            # Adjust prediction confidence based on similarity percentage\n            if class_confidence >= self.similarity_threshold:\n                return predicted.item(), 1.0\n            elif class_confidence >= 0.5:\n                # Adjust confidence based on similarity percentage\n                adjusted_confidence = 0.95 + 0.02 * similarity_percentage\n                return predicted.item(), min(1.0, adjusted_confidence)\n            else:\n                return None, None\n    \n    def calculate_similarity(self, image):\n        # Calculate similarity between learned parameters and input image features\n        with torch.no_grad():\n            features = self.features(image)\n            flattened_features = torch.flatten(features)\n            learned_parameters = torch.flatten(torch.cat([param.view(-1) for param in self.parameters()]))\n            similarity = torch.cosine_similarity(flattened_features, learned_parameters, dim=0)\n            return similarity.item()   \n\n\n# Load datasets using ToqiDataset\ntrain_dataset = ToqiDataset(root_dir='dataset/training_set')\n\n# Create an instance of the custom model\nmodel = ToqiNet(num_classes=train_dataset.num_classes)\n\n# Display model architecture\nprint(model)\n\n\n\n# Define the transform to be applied to the input image\ntransform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\n# Load the saved model\nif torch.cuda.is_available():\n    checkpoint = torch.load('ToqiNet2.weights')\nelse:\n    checkpoint = torch.load('ToqiNet2.weights', map_location=torch.device('cpu'))\n\nclass_to_idx = checkpoint['class_to_idx']\nidx_to_class = {idx: class_name for class_name, idx in class_to_idx.items()}\nmodel = ToqiNet(num_classes=len(class_to_idx))  # Use the length of class_to_idx\nmodel.load_state_dict(checkpoint['model_state_dict'])\nmodel.eval()\n\n# Move the model to the appropriate device\nmodel.to(model.device)\n\n# Load and preprocess the image\nimage_path = 'cat.10.jpg'  # Update with the path to your image\nimage = Image.open(image_path).convert(\"RGB\")\ninput_image = transform(image).unsqueeze(0)  # Add batch dimension\n\n# Move the input image to the appropriate device\ninput_image = input_image.to(model.device)\nclass_to_idx = checkpoint['class_to_idx']\nidx_to_class = {idx: class_name for class_name, idx in class_to_idx.items()}\n\n# Perform inference\nwith torch.no_grad():\n    output = model(input_image)\n    probabilities = torch.softmax(output, dim=1)\n    predicted_idx = torch.argmax(output).item()\n    predicted_class = idx_to_class[predicted_idx]\n    confidence = probabilities[0, predicted_idx].item() * 100\n\n# Display the image\nplt.imshow(image)\nplt.axis('off')\nplt.title(f'Predicted Class: {predicted_class}, Confidence: {confidence:.2f}%')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-03-29T06:24:38.516815Z","iopub.execute_input":"2024-03-29T06:24:38.517235Z","iopub.status.idle":"2024-03-29T06:24:44.113263Z","shell.execute_reply.started":"2024-03-29T06:24:38.517206Z","shell.execute_reply":"2024-03-29T06:24:44.112395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the saved model\ncheckpoint = torch.load('/kaggle/input/model/ToqiNet2.weights')\nprint(checkpoint.keys())  # Print out the keys in the loaded checkpoint\n","metadata":{"execution":{"iopub.status.busy":"2024-03-28T13:35:36.768526Z","iopub.execute_input":"2024-03-28T13:35:36.76941Z","iopub.status.idle":"2024-03-28T13:35:37.00572Z","shell.execute_reply.started":"2024-03-28T13:35:36.769377Z","shell.execute_reply":"2024-03-28T13:35:37.0048Z"},"trusted":true},"execution_count":null,"outputs":[]}]}