{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"provenance":[],"collapsed_sections":["vBJUqdOhBBIU"],"gpuType":"V28"},"accelerator":"TPU","kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":91498,"databundleVersionId":11655853,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"#Imports","metadata":{"id":"4t2gISgXawxL"}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.cm as cm\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport os\nimport shutil\nfrom PIL import Image\nimport torchvision\nimport random\nfrom torchvision import transforms,datasets,models\nimport math\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nimport torch.backends.cudnn as cudnn\nimport time\nfrom tempfile import TemporaryDirectory\nimport torch\ncudnn.benchmark = True","metadata":{"id":"1aU31DqJCHJ4","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:31.216698Z","iopub.execute_input":"2025-05-24T02:34:31.216919Z","iopub.status.idle":"2025-05-24T02:34:32.849076Z","shell.execute_reply.started":"2025-05-24T02:34:31.216902Z","shell.execute_reply":"2025-05-24T02:34:32.848464Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#data augmentation","metadata":{"id":"mP31RguVa4Yk"}},{"cell_type":"code","source":"brightness=(0.98, 1.02)\ngamma=(0.5, 1.1)\ngaussian_std=(0,0.02)\nresolution = (256 , 256)","metadata":{"id":"SvCG9U5d0Um8","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:32.849877Z","iopub.execute_input":"2025-05-24T02:34:32.850277Z","iopub.status.idle":"2025-05-24T02:34:32.854156Z","shell.execute_reply.started":"2025-05-24T02:34:32.850224Z","shell.execute_reply":"2025-05-24T02:34:32.853355Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def delete_np(y,indice):\n  y = np.concatenate((y[:indice],y[indice+1:]))\n  return y","metadata":{"id":"Cj1LMJBsyY3F","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:32.856193Z","iopub.execute_input":"2025-05-24T02:34:32.856887Z","iopub.status.idle":"2025-05-24T02:34:32.903093Z","shell.execute_reply.started":"2025-05-24T02:34:32.856864Z","shell.execute_reply":"2025-05-24T02:34:32.902415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def data_augmentation(img, brightness=(0.98, 1.02), gamma=(0.5, 1.1), gaussian_std=(0,0.02)):\n  img = (img + 1) / 2  # Map from [-1, 1] to [0, 1] if normalized\n\n  gamma_val = random.uniform(gamma[0], gamma[1])\n  img = transforms.functional.adjust_gamma(img, gamma_val)\n\n  brightness_val = random.uniform(brightness[0], brightness[1])\n  img = transforms.functional.adjust_brightness(img, brightness_val)\n  # Gaussian noise (if needed)\n  noise = torch.randn_like(img) * random.uniform(gaussian_std[0],gaussian_std[1])\n  img = img + noise\n\n  # Clamp and re-normalize to [-1, 1]\n  img = torch.clamp(img, 0, 1)  # First clamp to [0, 1]\n  img = img * 2 - 1  # Map back to [-1, 1]\n\n  return img","metadata":{"id":"gS695Z34ldhn","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:32.903908Z","iopub.execute_input":"2025-05-24T02:34:32.904165Z","iopub.status.idle":"2025-05-24T02:34:32.914017Z","shell.execute_reply.started":"2025-05-24T02:34:32.904147Z","shell.execute_reply":"2025-05-24T02:34:32.913346Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Classes","metadata":{}},{"cell_type":"code","source":"import os \nos.listdir('/kaggle/input/image-matching-challenge-2025/train')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:32.914796Z","iopub.execute_input":"2025-05-24T02:34:32.915078Z","iopub.status.idle":"2025-05-24T02:34:32.931279Z","shell.execute_reply.started":"2025-05-24T02:34:32.915063Z","shell.execute_reply":"2025-05-24T02:34:32.930559Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import DataLoader\nfrom sklearn.model_selection import KFold","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:32.932111Z","iopub.execute_input":"2025-05-24T02:34:32.932313Z","iopub.status.idle":"2025-05-24T02:34:34.089001Z","shell.execute_reply.started":"2025-05-24T02:34:32.932296Z","shell.execute_reply":"2025-05-24T02:34:34.088222Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Importação dos dados com o transfom fazendo a augmentação","metadata":{}},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize(resolution),\n    transforms.ToTensor(),  # [0, 1]\n    transforms.Normalize(mean=[0.5], std=[0.5]),  # [-1, 1]\n    #transforms.Grayscale(),\n    transforms.RandomApply(\n        [transforms.Lambda(lambda x: data_augmentation(x))],\n        p=0.5  # 50% chance to apply\n    ),\n])\n\nkaggle_data = torchvision.datasets.ImageFolder(\n    '/kaggle/input/image-matching-challenge-2025/train',\n    transform=transform)\n\ndata_loader = torch.utils.data.DataLoader(kaggle_data,batch_size=64,shuffle=True, num_workers=4)","metadata":{"id":"4XuSrIRs40Li","outputId":"c1505a60-c7f6-478a-a2b8-94f043d0fac9","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:34.089719Z","iopub.execute_input":"2025-05-24T02:34:34.091046Z","iopub.status.idle":"2025-05-24T02:34:36.677176Z","shell.execute_reply.started":"2025-05-24T02:34:34.091020Z","shell.execute_reply":"2025-05-24T02:34:36.676669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_names = kaggle_data.classes\nclasses_map = []\nfor i in enumerate(kaggle_data.classes):\n  classes_map.append(i)\nclasses_map = dict(classes_map)\n\n\ndevice = \"cuda\"\nprint(f\"Using {device} device\")","metadata":{"id":"HdfT8LHMEqu9","outputId":"e74e641a-95fa-4478-9cbf-ec66cd089d07","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:36.677825Z","iopub.execute_input":"2025-05-24T02:34:36.677998Z","iopub.status.idle":"2025-05-24T02:34:36.682879Z","shell.execute_reply.started":"2025-05-24T02:34:36.677984Z","shell.execute_reply":"2025-05-24T02:34:36.682274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dif_classes ={}\nfor label in range(13):\n    dif_classes[label] =0\nfor _,label in kaggle_data:\n    dif_classes[label] +=1","metadata":{"id":"OCP0n3iG9wqL","trusted":true,"execution":{"iopub.status.busy":"2025-05-24T02:34:52.907651Z","iopub.execute_input":"2025-05-24T02:34:52.908335Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y = list(dif_classes.values())\nx = list(dif_classes.keys())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns\nimport pandas as pd\nsns.barplot(x=x,y=y)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def imshow(inp, title=None):\n    \"\"\"Display image for Tensor.\"\"\"\n    inp = inp.numpy().transpose((1, 2, 0))\n    mean = np.array([0.5, 0.5, 0.5])\n    std = np.array([0.5, 0.5, 0.5])\n    inp = std * inp + mean\n    inp = np.clip(inp, 0, 1)\n    plt.imshow(inp)\n    if title is not None:\n        plt.title(title)\n    plt.pause(0.001)  # pause a bit so that plots are updated\n\n\n# Get a batch of training data\ninputs, classes = next(iter(kaggle_data))\n\n# Make a grid from batch\nout = torchvision.utils.make_grid(inputs)\n\nimshow(out,title =classes)","metadata":{"id":"uTKXcxoYu8AC","outputId":"aef58267-8ade-4692-c926-d0df0595a6d9","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm import tqdm\ndef train_model(model, criterion, optimizer, scheduler, train_loader,test_loader, num_epochs=25):\n    best_acc = 0.0\n    history = {'train_loss': [], 'train_acc': [], 'val_loss': [], 'val_acc': []}\n    for epoch in tqdm(range(num_epochs)):\n        print(f'Epoch {epoch}/{num_epochs-1}')\n        print('-' * 10)\n\n        for phase in ['train', 'val']:\n            model.train() if phase == 'train' else model.eval()\n\n            running_loss = 0.0\n            running_corrects = 0\n            if phase == 'train':\n                data_loader_phase = train_loader\n            else :\n                data_loader_phase =test_loader\n            dataset_size = len(data_loader_phase.dataset)\n            \n            \n            for inputs, labels in data_loader_phase:\n                inputs, labels = inputs.to(device), labels.to(device)\n                optimizer.zero_grad()\n\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(inputs)\n                    _, preds = torch.max(outputs, 1)\n                    loss = criterion(outputs, labels)\n\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n\n            epoch_loss = running_loss / dataset_size\n            epoch_acc = running_corrects.double() / dataset_size\n\n            history[f'{phase}_loss'].append(epoch_loss)\n            history[f'{phase}_acc'].append(epoch_acc.item())\n            print(f\"{phase} Loss: {epoch_loss} Acc: {epoch_acc}\")\n\n            if phase == 'train':\n                scheduler.step()\n\n            if phase == 'val':\n                if epoch_acc > best_acc:\n                    best_acc = epoch_acc\n                    torch.save(model.state_dict(), 'best_model.pt')\n    return model, history\n","metadata":{"id":"_yAWgsrmzNoL","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def visualize_model(model,num_images = 6):\n  was_training = model.training\n  model.eval()\n  images_so_far = 0\n  fig = plt.figure()\n  with torch.no_grad():\n    for i, (inputs,labels) in enumerate(kaggle_data_test):\n      inputs = inputs.to(device)\n      labels = inputs.to(device)\n\n      outputs = model(inputs)\n      _, preds = torch.max(outputs,1)\n\n      for j in range(inputs.size()[0]):\n        images_so_far+=1\n        ax = plt.subplot(num_images//2,2,images_so_far)\n        ax.axis('off')\n        ax.set_title(f'predicted:{class_names[preds[j]]}')\n        imshow(inputs.cpu.data[j])\n        if images_so_far == num_images:\n          model.train(mode=was_training)\n          return\n\n    model.train(mode=was_training)","metadata":{"id":"idRsuwUottEE","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader, Subset\ndef k_fold_cross_validation(kaggle_data=kaggle_data,batch_size =3,k_folds =2,num_workers=8):\n    results ={}\n    kf = KFold(n_splits=k_folds, shuffle=True)\n    \n    model_ft = models.resnet18(weights = 'IMAGENET1K_V1')\n    num_ftrs = model_ft.fc.in_features\n    model_ft.fc =nn.Linear(num_ftrs,len(class_names))\n    criterion = nn.CrossEntropyLoss()\n    optimizer_ft = optim.SGD(model_ft.parameters(),lr = 0.001, momentum =0.9)\n    exp_lr_scheduler=lr_scheduler.StepLR(optimizer_ft,step_size =7, gamma =0.1)\n\n    \n    for fold,(train_idx,val_idx) in tqdm(enumerate(kf.split(kaggle_data))):\n        print(f'FOLD {fold + 1}')\n        print('--------------------------------')\n        \n        # Create subsets\n        train_subsampler = Subset(kaggle_data, train_idx)\n        val_subsampler = Subset(kaggle_data, val_idx)\n        \n        # Create data loaders\n        train_loader = DataLoader(\n            train_subsampler,\n            batch_size=batch_size,\n            num_workers=num_workers,\n            shuffle=True  # Shuffle training data each epoch\n        )\n        \n        val_loader = DataLoader(\n            val_subsampler,\n            batch_size=batch_size,\n            num_workers=num_workers,\n            shuffle=False  # No need to shuffle validation data\n        )\n        \n    \n        model_ft = model_ft.to(device)\n    \n        model_ft , val_results  = train_model(model_ft,\n                               criterion,\n                               optimizer_ft, \n                               exp_lr_scheduler,\n                               train_loader,\n                               val_loader,\n                               num_epochs=10)\n    return val_results","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_ft = models.resnet18(weights = 'IMAGENET1K_V1')\nnum_ftrs = model_ft.fc.in_features\nmodel_ft.fc =nn.Linear(num_ftrs,len(class_names))\ncriterion = nn.CrossEntropyLoss()\noptimizer_ft = optim.SGD(model_ft.parameters(),lr = 0.001, momentum =0.9)\nexp_lr_scheduler=lr_scheduler.StepLR(optimizer_ft,step_size =7, gamma =0.1)\nmodel_ft = model_ft.to(device)","metadata":{"id":"UmXfEtwC-MVT","outputId":"b2b21e10-d6c6-4fe3-a8c6-385bb42ee40a","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import optuna\nimport torch.optim as optim\n\ndef objective(trial):\n    # Hyperparameters\n    batch = trial.suggest_int('batch', 3, 16)\n    lr = trial.suggest_float('lr', 0.0001, 0.1, log=True)  # Added log scale for better exploration\n    optimizer_name = trial.suggest_categorical('optimizer', ['SGD', 'Adam', 'Adadelta'])\n    \n    # Model setup\n    model_ft = models.resnet18(weights='IMAGENET1K_V1')\n    num_ftrs = model_ft.fc.in_features\n    model_ft.fc = nn.Linear(num_ftrs, len(class_names))\n    \n    # Optimizer selection\n    if optimizer_name == 'SGD':\n        optimizer_ft = optim.SGD(model_ft.parameters(), lr=lr)\n    elif optimizer_name == 'Adam':\n        optimizer_ft = optim.Adam(model_ft.parameters(), lr=lr)\n    elif optimizer_name == 'Adadelta':\n        optimizer_ft = optim.Adadelta(model_ft.parameters(), lr=lr)\n    \n    criterion = nn.CrossEntropyLoss()\n    exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)\n    model_ft = model_ft.to(device)\n    \n    # Validation\n    val_results = k_fold_cross_validation(kaggle_data=kaggle_data, batch_size=batch, k_folds=3)\n    \n    # Return the final validation accuracy\n    return float(val_results['val_acc'][-1])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"study = optuna.create_study(direction=\"maximize\")\nstudy.optimize(objective, n_trials=10)\n\ntrial = study.best_trial","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optuna.visualization.plot_optimization_history(study)\n\n#Plotting the accuracies for each hyperparameter for each trial.\n\noptuna.visualization.plot_slice(study)\n\n#Plotting the accuracy surface for the hyperparameters involved in the random forest model.\n\noptuna.visualization.plot_contour(study, params=[\"batch\", \"lr\",\"optimizer\"])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}