{"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"},"accelerator":"GPU","colab":{"gpuType":"T4","provenance":[],"name":"contrastive_learning"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":91451,"databundleVersionId":11223220,"sourceType":"competition"},{"sourceId":11635767,"sourceType":"datasetVersion","datasetId":7300681},{"sourceId":11635874,"sourceType":"datasetVersion","datasetId":7300750}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"","metadata":{"id":"jMKXZqum4UcZ"}},{"cell_type":"markdown","source":"**LBP WORK**","metadata":{"id":"yg56Ld8R7bYc"}},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nimport timm\nimport torch.nn.functional as F\nfrom tqdm.auto import tqdm\nfrom collections import defaultdict\nimport matplotlib.pyplot as plt\nimport cv2\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom torchvision.models import resnet18, ResNet18_Weights","metadata":{"id":"UZRuORbxO3Yp","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:24:37.9556Z","iopub.execute_input":"2025-05-01T09:24:37.955855Z","iopub.status.idle":"2025-05-01T09:24:42.031161Z","shell.execute_reply.started":"2025-05-01T09:24:37.95584Z","shell.execute_reply":"2025-05-01T09:24:42.030396Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ndef get_data_augmentation(s=1.0, image_size=224):\n    kernel_size = int(image_size * 0.1)\n    if kernel_size % 2 == 0:\n\n        kernel_size += 1\n\n    gaussian_blur = transforms.RandomApply(\n        [transforms.GaussianBlur(kernel_size=kernel_size, sigma=(0.1, 2.0))],\n        p=0.5,\n    )\n\n    augmentation = transforms.Compose([\n        transforms.RandomResizedCrop(image_size, scale=(0.6, 1.0), ratio=(3/4, 4/3)),\n        transforms.RandomHorizontalFlip(p=0.5),\n        gaussian_blur,\n        transforms.ToTensor()\n    ])\n    return augmentation\n\ntrain_transform = get_data_augmentation(s=1.0, image_size=224)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:16:01.818401Z","iopub.execute_input":"2025-05-01T09:16:01.818675Z","iopub.status.idle":"2025-05-01T09:16:01.824315Z","shell.execute_reply.started":"2025-05-01T09:16:01.818657Z","shell.execute_reply":"2025-05-01T09:16:01.823522Z"},"id":"L2xBLLEvHqMz"},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nclass AnimalReIDDataset(Dataset):\n    def __init__(self, df, base_path, transform=None):\n        self.df = df.reset_index(drop=True)\n        self.base_path = base_path\n        self.transform = transform\n        self.identity_to_label = {id_: idx for idx, id_ in enumerate(self.df['identity'].unique())}\n        self.labels = self.df['identity'].map(self.identity_to_label)\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        rel_path = row['path'].strip()\n        full_path = os.path.join(self.base_path, rel_path)\n\n        try:\n            image = Image.open(full_path).convert('RGB')\n        except Exception as e:\n            print(f\"Error loading image at {full_path}: {e}\")\n            image = Image.new('RGB', (224, 224), color='black')\n\n        label = self.labels.iloc[idx]\n        if self.transform:\n            view1 = self.transform(image)\n            view2 = self.transform(image)\n        return view1, view2, label\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:16:03.940923Z","iopub.execute_input":"2025-05-01T09:16:03.941164Z","iopub.status.idle":"2025-05-01T09:16:03.947581Z","shell.execute_reply.started":"2025-05-01T09:16:03.941149Z","shell.execute_reply":"2025-05-01T09:16:03.946945Z"},"id":"mw49l8dzHqMz"},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\ndef collate_fn(batch):\n    images = torch.cat([torch.stack([view1, view2]) for view1, view2, _ in batch], dim=0)\n    labels = torch.tensor([label for _, _, label in batch], dtype=torch.long)\n    return images, labels\n\n\n\nclass ReIDModel(nn.Module):\n    def __init__(self, embedding_dim=256):\n        super().__init__()\n\n        super(ReIDModel, self).__init__()\n        # Load the pretrained VGG16 model.\n        vgg16 = models.vgg16(pretrained=True)\n        self.features = vgg16.features\n        self.avgpool = vgg16.avgpool\n\n        self.flatten = nn.Flatten()\n    def forward(self, x):\n        x = self.features(x)\n        x = self.avgpool(x)\n        x = self.flatten(x)\n        x = F.normalize(x, p=2, dim=1)\n        return x\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:16:05.579234Z","iopub.execute_input":"2025-05-01T09:16:05.579978Z","iopub.status.idle":"2025-05-01T09:16:05.585649Z","shell.execute_reply.started":"2025-05-01T09:16:05.579952Z","shell.execute_reply":"2025-05-01T09:16:05.584886Z"},"id":"gS9K5MB5HqMz"},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"*VALIDATION AND TESTING PART*","metadata":{"id":"T56mi4SBe-mL"}},{"cell_type":"code","source":"\nclass MultiViewSupConLoss(nn.Module):\n    def __init__(self, temperature=0.2):\n        super(MultiViewSupConLoss, self).__init__()\n        self.temperature = temperature\n\n    def forward(self, features, labels):\n\n        device = features.device\n        if labels.dim() == 1 and labels.size(0) * 2 == features.size(0):\n            labels = labels.repeat_interleave(2)\n\n\n        labels = labels.contiguous().view(-1, 1)\n        mask = torch.eq(labels, labels.T).float().to(device)\n        sim_matrix = torch.div(torch.matmul(features, features.T), self.temperature)\n\n        logits_max, _ = torch.max(sim_matrix, dim=1, keepdim=True)\n        logits = sim_matrix - logits_max.detach()\n\n        logits_mask = torch.scatter(torch.ones_like(mask), 1,\n                                      torch.arange(features.size(0)).view(-1, 1).to(device), 0)\n        mask = mask * logits_mask\n        exp_logits = torch.exp(logits) * logits_mask\n        log_prob = logits - torch.log(exp_logits.sum(1, keepdim=True) + 1e-12)\n        mean_log_prob_pos = (mask * log_prob).sum(1) / (mask.sum(1) + 1e-12)\n\n        loss = -mean_log_prob_pos.mean()\n        return loss\n\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = ReIDModel(embedding_dim=256).to(device)","metadata":{"id":"4Qb_V8JRVtTq","outputId":"ece6388c-85ce-4024-cb1c-74b1ad90d988","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:16:07.65364Z","iopub.execute_input":"2025-05-01T09:16:07.653954Z","iopub.status.idle":"2025-05-01T09:16:12.997104Z","shell.execute_reply.started":"2025-05-01T09:16:07.653932Z","shell.execute_reply":"2025-05-01T09:16:12.995628Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\ntrain_csv_path = '/kaggle/input/data-base/metadata_database.csv'\nbase_image_dir = '/kaggle/input/animal-clef-2025'\n# val_csv_path='/content/metadata_val.csv'\ntrain_df = pd.read_csv(train_csv_path)\n# val_df=pd.read_csv(val_csv_path)\n\n\ntrain_dataset = AnimalReIDDataset(train_df, base_image_dir, transform=train_transform)\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2, collate_fn=collate_fn)\n\n# val_dataset = AnimalReIDDataset(val_df, base_image_dir, transform=train_transform)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=True, num_workers=2, collate_fn=collate_fn)","metadata":{"id":"J7fYljucohAQ","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:16:35.903371Z","iopub.execute_input":"2025-05-01T09:16:35.903834Z","iopub.status.idle":"2025-05-01T09:16:35.964539Z","shell.execute_reply.started":"2025-05-01T09:16:35.903813Z","shell.execute_reply":"2025-05-01T09:16:35.963914Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.optim as optim\nmodel = ReIDModel().to(device)\ncriterion = MultiViewSupConLoss(temperature=0.2)\noptimizer = optim.Adam(model.parameters(),lr=0.0001)\n\nnum_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\nprint(f\"Number of trainable parameters: {num_params}\")","metadata":{"id":"DsVl0KvIokl_","outputId":"d4c88c51-ab51-401d-c07d-0d17a336d288","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:16:38.110874Z","iopub.execute_input":"2025-05-01T09:16:38.111415Z","iopub.status.idle":"2025-05-01T09:16:39.795451Z","shell.execute_reply.started":"2025-05-01T09:16:38.111389Z","shell.execute_reply":"2025-05-01T09:16:39.794669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"augmentation = transforms.Compose([\n        transforms.ToTensor(),transforms.Resize((224,224))\n    ])\n\n\ndef load_and_preprocess_image(image_path, transform, device):\n    image = Image.open(image_path).convert('RGB')\n    image = transform(image)\n    # Add batch dimension\n    image = image.unsqueeze(0).to(device)\n    return image\n\ndef get_embedding(image_tensor, model):\n    with torch.no_grad():\n        embedding = model(image_tensor)\n    return embedding","metadata":{"id":"MLxaftvAxiSV","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:39.022642Z","iopub.execute_input":"2025-05-01T09:17:39.023197Z","iopub.status.idle":"2025-05-01T09:17:39.028871Z","shell.execute_reply.started":"2025-05-01T09:17:39.023158Z","shell.execute_reply":"2025-05-01T09:17:39.028178Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"start_epoch=0\nnum_epochs=10","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:41.3226Z","iopub.execute_input":"2025-05-01T09:17:41.32308Z","iopub.status.idle":"2025-05-01T09:17:41.326552Z","shell.execute_reply.started":"2025-05-01T09:17:41.323059Z","shell.execute_reply":"2025-05-01T09:17:41.32598Z"},"id":"DPgMDnwcHqM1"},"outputs":[],"execution_count":null},{"cell_type":"code","source":"p1='/kaggle/input/animal-clef-2025/images/SalamanderID2025/database/images/f0a166f9d2c6da14_1939.jpg'\n# 131\np2='/kaggle/input/animal-clef-2025/images/SalamanderID2025/database/images/dd9da1f5f7faff4c_1795.jpg'\n# 181\np3='/kaggle/input/animal-clef-2025/images/SalamanderID2025/database/images/150a35732ed087c0_178.jpg'\n# 181\nimg1=load_and_preprocess_image(p1,augmentation,device)\nimg2=load_and_preprocess_image(p2,augmentation,device)\nimg3=load_and_preprocess_image(p3,augmentation,device)\n# only images 2&3 have same class","metadata":{"id":"ovRK3q4gJ-QO","trusted":true,"execution":{"iopub.status.busy":"2025-05-03T10:00:16.208865Z","iopub.execute_input":"2025-05-03T10:00:16.209158Z","iopub.status.idle":"2025-05-03T10:00:16.213015Z","shell.execute_reply.started":"2025-05-03T10:00:16.209136Z","shell.execute_reply":"2025-05-03T10:00:16.212248Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tqdm import tqdm \n\nmodel.train()\nmin_loss = float('inf') \nstart_epoch = 0\n\nwhile start_epoch < num_epochs:\n    training_loss = 0.0\n    print(f\"Epoch [{start_epoch+1}/{num_epochs}]\")\n\n\n    e1 = get_embedding(img1, model)\n    e2 = get_embedding(img2, model)\n    e3 = get_embedding(img3, model)\n    print(f\" e1·e2 = { (e1[0] * e2[0]).sum()}\")\n    print(f\" e2·e3 = { (e2[0] * e3[0]).sum()}\")\n    print(f\" e1·e3 = { (e1[0] * e3[0]).sum()}\")\n\n    loop = tqdm(train_loader, desc=f\"Epoch {start_epoch+1}/{num_epochs}\", ncols=100)\n    for images, labels in loop:\n        images, labels = images.to(device), labels.to(device)\n        features = model(images)\n        loss = criterion(features, labels)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        training_loss += loss.item()\n        # update tqdm bar with current batch loss\n        loop.set_postfix(batch_loss=loss.item())\n\n    avg_loss = training_loss / len(train_loader)\n    if avg_loss < min_loss:\n        min_loss = avg_loss\n\n    print(f\"Epoch completed. Avg train Loss: {avg_loss:.4f}\")\n    print(f\"Minimum training loss so far = {min_loss:.4f}\\n\")\n\n    start_epoch += 1\n\nprint(\"Training finished.\")\n","metadata":{"id":"6Ve62_71lYWR","outputId":"66c82bd3-b048-4f9f-9ee0-e6712b3fd4cf","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:35:57.838882Z","iopub.execute_input":"2025-05-01T09:35:57.839491Z","iopub.status.idle":"2025-05-01T09:35:57.843496Z","shell.execute_reply.started":"2025-05-01T09:35:57.839469Z","shell.execute_reply":"2025-05-01T09:35:57.842733Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# visulize output of model with some sample images","metadata":{"id":"mBoxsTcAHqM1"}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\n\nplt.imshow(mpimg.imread(p1))","metadata":{"id":"D4Ph_1oiKWjX","outputId":"6e8c490d-134a-45c7-8e09-a942db7fcd91","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:02.90362Z","iopub.execute_input":"2025-05-01T09:17:02.903897Z","iopub.status.idle":"2025-05-01T09:17:03.325536Z","shell.execute_reply.started":"2025-05-01T09:17:02.903877Z","shell.execute_reply":"2025-05-01T09:17:03.32473Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(mpimg.imread(p2))","metadata":{"id":"Bl7LsIYAKeoI","outputId":"19177f16-5d93-416f-a1c2-679b48c9faaf","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:03.326785Z","iopub.execute_input":"2025-05-01T09:17:03.326997Z","iopub.status.idle":"2025-05-01T09:17:03.748629Z","shell.execute_reply.started":"2025-05-01T09:17:03.32698Z","shell.execute_reply":"2025-05-01T09:17:03.747867Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(mpimg.imread(p3))","metadata":{"id":"iewGkYH-Kmes","outputId":"a16dbc83-d937-4ebe-ea66-dde5eead9f91","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:03.7493Z","iopub.execute_input":"2025-05-01T09:17:03.749549Z","iopub.status.idle":"2025-05-01T09:17:04.341783Z","shell.execute_reply.started":"2025-05-01T09:17:03.749531Z","shell.execute_reply":"2025-05-01T09:17:04.34104Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"e1=get_embedding(img1, model)\ne2=get_embedding(img2, model)\ne3=get_embedding(img3, model)","metadata":{"id":"4Xt1i9dCKtOk","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:04.343456Z","iopub.execute_input":"2025-05-01T09:17:04.343984Z","iopub.status.idle":"2025-05-01T09:17:04.964832Z","shell.execute_reply.started":"2025-05-01T09:17:04.343959Z","shell.execute_reply":"2025-05-01T09:17:04.964279Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sum((e1[0])*(e2[0]))","metadata":{"id":"qQtxXtKCK0jd","outputId":"724ca9cf-a1f7-4637-dd90-0ee767a05522","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:17:04.965467Z","iopub.execute_input":"2025-05-01T09:17:04.965722Z","iopub.status.idle":"2025-05-01T09:17:05.46911Z","shell.execute_reply.started":"2025-05-01T09:17:04.965701Z","shell.execute_reply":"2025-05-01T09:17:05.468274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sum((e2[0])*(e3[0]))","metadata":{"id":"2zT9XD6tK3G0","outputId":"b5c5f085-eb96-47d3-b312-03060cb0d254","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:09:22.324927Z","iopub.execute_input":"2025-05-01T09:09:22.325244Z","iopub.status.idle":"2025-05-01T09:09:22.442733Z","shell.execute_reply.started":"2025-05-01T09:09:22.325221Z","shell.execute_reply":"2025-05-01T09:09:22.442058Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sum((e1[0])*(e3[0]))","metadata":{"id":"_wpM82shUTqL","outputId":"c73e0f11-63de-4187-b5d8-688477ba6604","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:09:23.829576Z","iopub.execute_input":"2025-05-01T09:09:23.83016Z","iopub.status.idle":"2025-05-01T09:09:24.111928Z","shell.execute_reply.started":"2025-05-01T09:09:23.830139Z","shell.execute_reply":"2025-05-01T09:09:24.111252Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nBASE_PATH    = '/kaggle/input/animal-clef-2025'\nDB_CSV       = '/kaggle/input/data-base/metadata_database.csv'\nQ_CSV        = '/kaggle/input/data-base/metadata_query.csv'\ndb_meta = pd.read_csv(DB_CSV)\ndb_df   = db_meta.copy()\nclass TrainDataset(Dataset):\n    def __init__(self, df, root, tfm):\n        self.df, self.root, self.tfm = df.reset_index(drop=True), root, tfm\n    def __len__(self): return len(self.df)\n    def __getitem__(self, i):\n        row = self.df.iloc[i]\n        img = Image.open(os.path.join(self.root, row['path'])).convert('RGB')\n        return self.tfm(img), label2idx[row['identity']]\n\nclass QueryDataset(Dataset):\n    def __init__(self, csv, root, tfm):\n        tmp = pd.read_csv(csv).reset_index(drop=True)\n        self.df, self.root, self.tfm = tmp, root, tfm\n    def __len__(self): return len(self.df)\n    def __getitem__(self, i):\n        row = self.df.iloc[i]\n        img = Image.open(os.path.join(self.root, row['path'])).convert('RGB')\n        return self.tfm(img), int(row['image_id'])\n\nquery_loader = DataLoader(\n    QueryDataset(Q_CSV, BASE_PATH, augmentation),\n    batch_size=32, shuffle=False,\n    num_workers=2, pin_memory=True\n)","metadata":{"trusted":true,"id":"RTnMamffHqM3","execution":{"iopub.status.busy":"2025-05-01T09:23:36.715835Z","iopub.execute_input":"2025-05-01T09:23:36.716437Z","iopub.status.idle":"2025-05-01T09:23:36.75205Z","shell.execute_reply.started":"2025-05-01T09:23:36.716413Z","shell.execute_reply":"2025-05-01T09:23:36.751548Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── Embedding extractor (now converts every img_id  to vectors) ────────────────────\ndef extract_embeddings(loader):\n    model.eval()\n    feats_list, ids_list = [], []\n    with torch.no_grad():\n        for imgs, img_ids in tqdm(loader, desc=\"Embedding\"):\n            imgs = imgs.to(device)\n            f    = model(imgs)\n            f    = F.normalize(f, dim=1)\n            feats_list.append(f.cpu())\n            ids_list.extend([int(x) for x in img_ids])\n    return torch.cat(feats_list, dim=0), ids_list\n\n# ── Build prototypes by identity string ───────────────────────────────────────\ndb_feats, db_ids = extract_embeddings(\n    DataLoader(QueryDataset(DB_CSV, BASE_PATH, augmentation),\n               batch_size=32, shuffle=False,\n               num_workers=2, pin_memory=True)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:26:59.119193Z","iopub.execute_input":"2025-05-01T09:26:59.11979Z","iopub.status.idle":"2025-05-01T09:30:12.133814Z","shell.execute_reply.started":"2025-05-01T09:26:59.119754Z","shell.execute_reply":"2025-05-01T09:30:12.132742Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# map image_id → identity (from our head-100 db_meta)\nid_map = db_meta.set_index('image_id')['identity']\n\nproto_map = defaultdict(list)\nfor feat, img_id in zip(db_feats, db_ids):\n    ident = id_map.loc[img_id]   # now img_id is an int, so no KeyError\n    proto_map[ident].append(feat)\n\nproto_idents, prototypes = [], []\nfor ident, feats in proto_map.items():\n    stacked = torch.stack(feats, dim=0)\n    mean_p  = F.normalize(stacked.mean(0), dim=0)\n    proto_idents.append(ident)\n    prototypes.append(mean_p)\nprototypes = torch.stack(prototypes).to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:30:41.230569Z","iopub.execute_input":"2025-05-01T09:30:41.231122Z","iopub.status.idle":"2025-05-01T09:30:41.762116Z","shell.execute_reply.started":"2025-05-01T09:30:41.231098Z","shell.execute_reply":"2025-05-01T09:30:41.761554Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"q_feats, q_ids = extract_embeddings(query_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:30:45.147432Z","iopub.execute_input":"2025-05-01T09:30:45.148151Z","iopub.status.idle":"2025-05-01T09:31:43.523955Z","shell.execute_reply.started":"2025-05-01T09:30:45.148127Z","shell.execute_reply":"2025-05-01T09:31:43.522881Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = []\nTHreshold=0.7  # try with changing the threshold value\n\n# if two images have a similarity score of >threshold then they are taken to have same class\n\nfor feat, img_id in zip(q_feats.to(device), q_ids):\n    sims, idx = F.cosine_similarity(feat.unsqueeze(0), prototypes).max(0)\n    print(sims.item())\n    pred = proto_idents[idx.item()] if sims.item() >=THreshold else 'new_individual'\n    results.append({'image_id': img_id, 'identity': pred})\n\nsubm_df = pd.DataFrame(results, columns=['image_id','identity'])\nsubm_df.to_csv(f'submission_fine_tunee.csv', index=False)\n\nprint(f\"REsults save in submission.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T09:38:00.786809Z","iopub.execute_input":"2025-05-01T09:38:00.787516Z","iopub.status.idle":"2025-05-01T09:38:08.993517Z","shell.execute_reply.started":"2025-05-01T09:38:00.787491Z","shell.execute_reply":"2025-05-01T09:38:08.992927Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}