### commons.setup_logging Source: https://context7.com/gmberton/cosplace/llms.txt Configures dual-file logging by creating an output directory and attaching INFO-level and DEBUG-level file handlers, plus a configurable console handler to the root logger. Used at the start of every training and evaluation run. ```APIDOC ## commons.setup_logging(output_folder, exist_ok, console, info_filename, debug_filename) ### Description Configures dual-file logging. Creates an output directory and attaches `INFO`-level and `DEBUG`-level file handlers plus a configurable console handler to the root logger. Used at the start of every training and evaluation run. ### Parameters - **output_folder** (string) - The path to the directory where log files will be saved. - **exist_ok** (boolean) - If `False`, raises `FileExistsError` if the output folder already exists. - **console** (string) - Specifies the logging level for the console output (e.g., "debug", "info"). - **info_filename** (string) - The name of the file for INFO-level logs. - **debug_filename** (string) - The name of the file for DEBUG-level logs. ### Usage ```python from commons import setup_logging import logging setup_logging( output_folder="logs/my_run/2024-01-01_12-00-00", exist_ok=False, # raise FileExistsError if folder already exists console="debug", # print DEBUG+ messages to stdout info_filename="info.log", debug_filename="debug.log" ) logging.info("Training started") # → info.log + debug.log + console logging.debug("Batch 1 loaded") # → debug.log + console only ``` ### Example Output ``` 2024-01-01 12:00:01 Training started 2024-01-01 12:00:01 Batch 1 loaded ``` ``` -------------------------------- ### Setup Dual-File Logging Source: https://context7.com/gmberton/cosplace/llms.txt Configures logging to both INFO and DEBUG level files, along with an optional console handler. Creates the output directory if it doesn't exist. Use `exist_ok=False` to prevent overwriting. ```python from commons import setup_logging import logging setup_logging( output_folder="logs/my_run/2024-01-01_12-00-00", exist_ok=False, # raise FileExistsError if folder already exists console="debug", # print DEBUG+ messages to stdout info_filename="info.log", debug_filename="debug.log" ) logging.info("Training started") # → info.log + debug.log + console logging.debug("Batch 1 loaded") # → debug.log + console only # Output: # 2024-01-01 12:00:01 Training started # 2024-01-01 12:00:01 Batch 1 loaded ``` -------------------------------- ### Initialize TestDataset for Evaluation Source: https://context7.com/gmberton/cosplace/llms.txt Loads and prepares the test/validation dataset, including database and query images, and pre-computes nearest neighbors for positive matching. Ensure the dataset folder contains 'database/' and 'queries/' subfolders. ```python from datasets.test_dataset import TestDataset # Val set folder must contain subfolders: database/ and queries/ (or queries_v1/) val_ds = TestDataset( dataset_folder="path/to/sf_xl/processed/val", database_folder="database", queries_folder="queries", positive_dist_threshold=25, # meters image_size=512, resize_test_imgs=False ) print(val_ds) # < val - #q: 1000; #db: 24000 > # Iterate images (database first, then queries) img_tensor, index = val_ds[0] print(img_tensor.shape) # torch.Size([3, H, W]) # Retrieve ground-truth positives for query 0 positives = val_ds.get_positives() print(f"Query 0 has {len(positives[0])} positive database images") ``` -------------------------------- ### MarginCosineProduct Initialization Source: https://context7.com/gmberton/cosplace/llms.txt Implements the large-margin cosine loss (CosFace) as a learnable linear layer, used during training. ```APIDOC ## MarginCosineProduct(in_features, out_features, s, m) ### Description Implements the large-margin cosine loss (CosFace) as a learnable linear layer. Computes cosine similarity, applies a margin, and scales before cross-entropy. ### Parameters - **in_features** (int): Dimension of the input features (descriptors). - **out_features** (int): Number of classes. - **s** (float): Feature scale. - **m** (float): Cosine margin. ### Example ```python import torch from cosface_loss import MarginCosineProduct classifier = MarginCosineProduct( in_features=512, out_features=12450, s=30.0, m=0.40 ).to("cuda") ``` ``` -------------------------------- ### Initialize MarginCosineProduct Classifier Source: https://context7.com/gmberton/cosplace/llms.txt Sets up a CosFace loss classifier for training. This involves defining the input and output feature dimensions, scaling factor 's', and margin 'm'. The classifier is typically placed on the CUDA device for training. ```python import torch from cosface_loss import MarginCosineProduct # Classifier for a group with 12450 classes and 512-dim descriptors classifier = MarginCosineProduct( in_features=512, out_features=12450, s=30.0, # feature scale m=0.40 # cosine margin ).to("cuda") criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam(classifier.parameters(), lr=0.01) ``` -------------------------------- ### Train CosPlace with Automatic Mixed Precision Source: https://github.com/gmberton/cosplace/blob/main/README.md Enable Automatic Mixed Precision (AMP) to potentially speed up training. Note that the paper's results were obtained without AMP. ```bash python3 train.py --use_amp16 ``` -------------------------------- ### Run Full CosPlace Training Pipeline Source: https://context7.com/gmberton/cosplace/llms.txt Executes the end-to-end CosPlace training script. Options include specifying dataset folders, backbone architecture, descriptor dimensions, and enabling mixed-precision training (AMP). Can resume interrupted training from a checkpoint. ```bash python3 train.py \ --train_set_folder path/to/sf_xl/raw/train/database \ --val_set_folder path/to/sf_xl/processed/val \ --test_set_folder path/to/sf_xl/processed/test ``` ```bash python3 train.py \ --backbone ResNet50 \ --fc_output_dim 128 \ --use_amp16 \ --train_set_folder path/to/sf_xl/raw/train/database \ --val_set_folder path/to/sf_xl/processed/val \ --test_set_folder path/to/sf_xl/processed/test ``` ```bash python3 train.py \ --resume_train logs/default/2024-01-01_12-00-00/last_checkpoint.pth \ --train_set_folder path/to/sf_xl/raw/train/database \ --val_set_folder path/to/sf_xl/processed/val \ --test_set_folder path/to/sf_xl/processed/test ``` ```bash python3 train.py \ --backbone ResNet50 --fc_output_dim 512 \ --num_preds_to_save 3 --save_only_wrong_preds \ --exp_name cosplace_r50_512 \ --train_set_folder path/to/sf_xl/raw/train/database \ --val_set_folder path/to/sf_xl/processed/val \ --test_set_folder path/to/sf_xl/processed/test # Output logs and checkpoints saved to: logs/cosplace_r50_512// ``` -------------------------------- ### Initialize CosPlace Training Dataset Source: https://context7.com/gmberton/cosplace/llms.txt Initialize the TrainDataset for CosPlace, which partitions geo-tagged images into spatial and angular classes for training. The dataset grouping is cached on disk for efficiency. Ensure the 'args' namespace contains necessary parameters for augmentation and image processing. ```python import argparse from datasets.train_dataset import TrainDataset # Minimal args namespace required by TrainDataset args = argparse.Namespace( augmentation_device="cpu", brightness=0.7, contrast=0.7, saturation=0.7, hue=0.5, random_resized_crop=0.5, image_size=512, ) # Example instantiation (dataset_folder, M, alpha, N, L, current_group, min_images_per_class need to be provided) # dataset = TrainDataset(args, dataset_folder="path/to/dataset", M=100, alpha=10, N=10, L=10, current_group=0, min_images_per_class=10) ``` -------------------------------- ### Initialize TrainDataset for SF-XL Training Source: https://context7.com/gmberton/cosplace/llms.txt Instantiates the TrainDataset to create groups of training data from the SF-XL dataset. Configure parameters like cell size, heading bin size, and spatial/heading strides. ```python dataset = TrainDataset( args=args, dataset_folder="path/to/sf_xl/raw/train/database", M=10, # cell side length in meters alpha=30, # heading bin size in degrees N=5, # spatial stride between groups L=2, # heading stride between groups current_group=0, min_images_per_class=10 ) print(f"Classes in group 0: {len(dataset)}") # e.g. 12450 print(f"Images in group 0: {dataset.get_images_num()}") # e.g. 186700 # Each item returns (image_tensor, class_index, image_path) tensor_img, class_idx, path = dataset[0] print(tensor_img.shape) # torch.Size([3, 512, 512]) ``` -------------------------------- ### torch.hub.load Source: https://context7.com/gmberton/cosplace/llms.txt Downloads and instantiates a CosPlace model pre-trained on SF-XL directly from GitHub releases. This allows for plug-and-play inference without local cloning. Backbone and descriptor dimensionality are configurable. ```APIDOC ## torch.hub.load ### Description Load a pre-trained CosPlace model via PyTorch Hub. Downloads and instantiates a CosPlace model pre-trained on SF-XL directly from GitHub releases. No local cloning required. Backbone and descriptor dimensionality are configurable. ### Parameters - **repo_or_dir** (string) - "gmberton/cosplace" - **model** (string) - "get_trained_model" - **backbone** (string) - The backbone architecture to use (e.g., "ResNet50"). - **fc_output_dim** (int) - The dimensionality of the output descriptors. ### Available Configurations - VGG16: 64, 128, 256, 512 - ResNet18: 32, 64, 128, 256, 512 - ResNet50: 32, 64, 128, 256, 512, 1024, 2048 - ResNet101: 32, 64, 128, 256, 512, 1024, 2048 - ResNet152: 32, 64, 128, 256, 512, 1024, 2048 ### Request Example ```python import torch # Load ResNet-50 with 2048-dim descriptors (best accuracy) model = torch.hub.load( "gmberton/cosplace", "get_trained_model", backbone="ResNet50", fc_output_dim=2048 ) model.eval() import torchvision.transforms as T from PIL import Image preprocess = T.Compose([ T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) query_tensor = preprocess(Image.open("query.jpg").convert("RGB")).unsqueeze(0) with torch.no_grad(): desc = model(query_tensor) # shape: [1, 2048] print(desc.shape) # torch.Size([1, 2048]) ``` ``` -------------------------------- ### Train CosPlace with Custom Backbone and Output Dimension Source: https://github.com/gmberton/cosplace/blob/main/README.md Modify the training process by specifying a different backbone architecture (e.g., ResNet50) and the desired dimensionality for the output descriptors. ```bash python3 train.py --backbone ResNet50 --fc_output_dim 128 ``` -------------------------------- ### TestDataset Initialization Source: https://context7.com/gmberton/cosplace/llms.txt Initializes the TestDataset for evaluation, loading database and query images, and pre-computing positive sets. ```APIDOC ## TestDataset(dataset_folder, database_folder, queries_folder, positive_dist_threshold, image_size, resize_test_imgs) ### Description Evaluation dataset that loads database and query images from a structured test/val folder, reads UTM coordinates from filenames, and pre-computes per-query positive sets using `NearestNeighbors`. ### Parameters - **dataset_folder** (str): Path to the processed test/val folder. - **database_folder** (str): Subfolder containing database images. - **queries_folder** (str): Subfolder containing query images. - **positive_dist_threshold** (float): Maximum distance in meters to consider an image as a positive match. - **image_size** (int): The target size for images. - **resize_test_imgs** (bool): Whether to resize test images. ### Example ```python from datasets.test_dataset import TestDataset val_ds = TestDataset( dataset_folder="path/to/sf_xl/processed/val", database_folder="database", queries_folder="queries", positive_dist_threshold=25, image_size=512, resize_test_imgs=False ) ``` ``` -------------------------------- ### TrainDataset Initialization Source: https://context7.com/gmberton/cosplace/llms.txt Initializes the TrainDataset for creating groups from the SF-XL training folder. It allows configuration of cell size, heading bin size, spatial stride, and heading stride. ```APIDOC ## TrainDataset ### Description Initializes the training dataset, allowing for the creation of spatial and heading groups from a raw dataset folder. ### Parameters - **args**: Arguments object containing various configuration settings. - **dataset_folder** (str): Path to the raw training dataset. - **M** (int): Cell side length in meters. - **alpha** (int): Heading bin size in degrees. - **N** (int): Spatial stride between groups. - **L** (int): Heading stride between groups. - **current_group** (int): The index of the current group to process. - **min_images_per_class** (int): Minimum number of images required per class. ### Example ```python from datasets.train_dataset import TrainDataset dataset = TrainDataset( args=args, dataset_folder="path/to/sf_xl/raw/train/database", M=10, alpha=30, N=5, L=2, current_group=0, min_images_per_class=10 ) ``` ``` -------------------------------- ### Train CosPlace Model Source: https://github.com/gmberton/cosplace/blob/main/README.md Use this command to train a CosPlace model. Specify the paths to your training, validation, and testing datasets. The script automatically handles dataset splitting and caching. ```bash python3 train.py --train_set_folder path/to/sf_xl/raw/train/database --val_set_folder path/to/sf_xl/processed/val --test_set_folder path/to/sf_xl/processed/test ``` -------------------------------- ### Load Pre-trained CosPlace Model via PyTorch Hub Source: https://context7.com/gmberton/cosplace/llms.txt Load a CosPlace model pre-trained on the SF-XL dataset directly from GitHub releases using torch.hub.load. This allows for plug-and-play inference without local training. Ensure the query tensor is preprocessed and normalized. ```python import torch # Load ResNet-50 with 2048-dim descriptors (best accuracy) model = torch.hub.load( "gmberton/cosplace", "get_trained_model", backbone="ResNet50", fc_output_dim=2048 ) model.eval() # Available backbone / fc_output_dim combinations: # VGG16: 64, 128, 256, 512 # ResNet18: 32, 64, 128, 256, 512 # ResNet50: 32, 64, 128, 256, 512, 1024, 2048 # ResNet101: 32, 64, 128, 256, 512, 1024, 2048 # ResNet152: 32, 64, 128, 256, 512, 1024, 2048 import torchvision.transforms as T from PIL import Image preprocess = T.Compose([ T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) query_tensor = preprocess(Image.open("query.jpg").convert("RGB")).unsqueeze(0) with torch.no_grad(): desc = model(query_tensor) # shape: [1, 2048] print(desc.shape) # torch.Size([1, 2048]) ``` -------------------------------- ### util.save_checkpoint / util.resume_train Source: https://context7.com/gmberton/cosplace/llms.txt Manages training checkpoints. `save_checkpoint` serializes the full training state (model weights, optimizer state, classifiers, etc.) to disk, and `resume_train` restores this state to continue an interrupted training run. ```APIDOC ## util.save_checkpoint / util.resume_train ### Description Checkpoint management functions. `save_checkpoint` serializes the full training state (model weights, optimizer state, all group classifiers and their optimizers, best recall) to disk after every epoch, and separately saves the best model weights. `resume_train` restores all of these from a checkpoint file to continue an interrupted training run. ### `util.save_checkpoint` Parameters - **state** (dict) - A dictionary containing the training state to save. - "epoch_num" (int) - The current epoch number. - "model_state_dict" (dict) - The state dictionary of the main model. - "optimizer_state_dict" (dict) - The state dictionary of the main optimizer. - "classifiers_state_dict" (list of dicts) - State dictionaries for group classifiers. - "optimizers_state_dict" (list of dicts) - State dictionaries for classifier optimizers. - "best_val_recall1" (float) - The best validation recall at rank 1. - **is_best** (boolean) - If `True`, saves the checkpoint as the best model. - **output_folder** (string) - The directory to save the checkpoint files. ### `util.resume_train` Parameters - **args** (object) - An object containing training arguments, including `resume_train` path and `device`. - **output_folder** (string) - The directory to save resumed training logs. - **model** (object) - The model instance to load state into. - **optimizer** (object) - The optimizer instance to load state into. - **classifiers** (list of objects) - List of classifier instances to load state into. - **cls_optimizers** (list of objects) - List of classifier optimizer instances to load state into. ### Usage ```python import torch from cosplace_model import cosplace_network from cosface_loss import MarginCosineProduct import util # --- Saving --- model = cosplace_network.GeoLocalizationNet("ResNet50", 512) optimizer = torch.optim.Adam(model.parameters(), lr=1e-5) classifiers = [MarginCosineProduct(512, 5000) for _ in range(8)] cls_optimizers = [torch.optim.Adam(c.parameters(), lr=0.01) for c in classifiers] util.save_checkpoint( state={ "epoch_num": 5, "model_state_dict": model.state_dict(), "optimizer_state_dict": optimizer.state_dict(), "classifiers_state_dict": [c.state_dict() for c in classifiers], "optimizers_state_dict": [o.state_dict() for o in cls_optimizers], "best_val_recall1": 87.3, }, is_best=True, output_folder="logs/my_run/2024-01-01_12-00-00" ) # Saves: last_checkpoint.pth and best_model.pth # --- Resuming --- import argparse args = argparse.Namespace(device="cuda", groups_num=8, resume_train="logs/my_run/.../last_checkpoint.pth") model, optimizer, classifiers, cls_optimizers, best_recall, start_epoch = util.resume_train( args, "logs/my_run/resumed/", model, optimizer, classifiers, cls_optimizers ) print(f"Resuming from epoch {start_epoch}, best R@1 = {best_recall:.1f}") # Output: # Resuming from epoch 5, best R@1 = 87.3 ``` ``` -------------------------------- ### Save and Resume Training Checkpoints Source: https://context7.com/gmberton/cosplace/llms.txt Utilities for saving the complete training state (model, optimizer, classifiers) and resuming an interrupted training run. `save_checkpoint` saves both the last and best models. ```python import torch from cosplace_model import cosplace_network from cosface_loss import MarginCosineProduct import util # --- Saving --- model = cosplace_network.GeoLocalizationNet("ResNet50", 512) optimizer = torch.optim.Adam(model.parameters(), lr=1e-5) classifiers = [MarginCosineProduct(512, 5000) for _ in range(8)] cls_optimizers = [torch.optim.Adam(c.parameters(), lr=0.01) for c in classifiers] util.save_checkpoint( state={ "epoch_num": 5, "model_state_dict": model.state_dict(), "optimizer_state_dict": optimizer.state_dict(), "classifiers_state_dict": [c.state_dict() for c in classifiers], "optimizers_state_dict": [o.state_dict() for o in cls_optimizers], "best_val_recall1": 87.3, }, is_best=True, output_folder="logs/my_run/2024-01-01_12-00-00" ) # Saves: last_checkpoint.pth and best_model.pth # --- Resuming --- import argparse args = argparse.Namespace(device="cuda", groups_num=8, resume_train="logs/my_run/.../last_checkpoint.pth") model, optimizer, classifiers, cls_optimizers, best_recall, start_epoch = util.resume_train( args, "logs/my_run/resumed/", model, optimizer, classifiers, cls_optimizers ) print(f"Resuming from epoch {start_epoch}, best R@1 = {best_recall:.1f}") # Resuming from epoch 5, best R@1 = 87.3 ``` -------------------------------- ### Evaluate Trained CosPlace Model Checkpoint Source: https://context7.com/gmberton/cosplace/llms.txt Loads a saved model and evaluates its performance on a test set, printing retrieval metrics. Can optionally save visualization images of predictions. Specify `--save_dir` to customize the output directory for visualizations. ```bash python3 eval.py \ --backbone ResNet50 \ --fc_output_dim 2048 \ --resume_model path/to/best_model.pth \ --test_set_folder path/to/sf_xl/processed/test ``` ```bash python3 eval.py \ --backbone ResNet50 \ --fc_output_dim 512 \ --resume_model path/to/best_model.pth \ --test_set_folder path/to/stlucia \ --num_preds_to_save 3 \ --save_dir cosplace_on_stlucia # Expected output: # < test - #q: 1200; #db: 30000 >: R@1: 89.3, R@5: 95.1, R@10: 96.8, R@20: 97.5 # Predictions saved to: logs/cosplace_on_stlucia//preds/ ``` -------------------------------- ### Build and Infer with GeoLocalizationNet Source: https://context7.com/gmberton/cosplace/llms.txt Instantiate the core GeoLocalizationNet model, which wraps a torchvision backbone with aggregation and projection layers for generating unit-normalized image descriptors. Ensure the input image tensor is normalized and has the correct shape before inference. ```python import torch from cosplace_model import cosplace_network # Build a ResNet-50 model with 512-dim descriptors, training only the last two blocks model = cosplace_network.GeoLocalizationNet( backbone="ResNet50", fc_output_dim=512, train_all_layers=False # freeze layers before conv_3 ) model = model.to("cuda").eval() # Run inference on a single normalized image tensor import torchvision.transforms as T from PIL import Image transform = T.Compose([ T.Resize(512), T.CenterCrop(512), T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) img = transform(Image.open("query.jpg").convert("RGB")).unsqueeze(0).to("cuda") with torch.no_grad(): descriptor = model(img) # shape: [1, 512] print(descriptor.shape) # torch.Size([1, 512]) print(descriptor.norm(dim=1)) # tensor([1.0000]) — unit-normalized ``` -------------------------------- ### Evaluate Model Performance with test.test Source: https://context7.com/gmberton/cosplace/llms.txt Computes Recall@K metrics by extracting descriptors, building a FAISS index, and retrieving nearest neighbors. Optionally saves prediction images for inspection. Requires a trained model and a prepared test dataset. ```python import torch import argparse import test from cosplace_model import cosplace_network from datasets.test_dataset import TestDataset args = argparse.Namespace( device="cuda", fc_output_dim=512, infer_batch_size=16, num_workers=4, num_preds_to_save=3, save_only_wrong_preds=False, output_folder="logs/my_experiment/2024-01-01_00-00-00", positive_dist_threshold=25, image_size=512, resize_test_imgs=False, ) model = cosplace_network.GeoLocalizationNet("ResNet50", args.fc_output_dim) model.load_state_dict(torch.load("best_model.pth")) model = model.to(args.device) test_ds = TestDataset( dataset_folder="path/to/sf_xl/processed/test", queries_folder="queries_v1", positive_dist_threshold=args.positive_dist_threshold, ) recalls, recalls_str = test.test(args, test_ds, model, num_preds_to_save=3) print(recalls_str) # R@1: 89.3, R@5: 95.1, R@10: 96.8, R@20: 97.5 # Prediction images saved to: logs/my_experiment/.../preds/000.jpg etc. ``` -------------------------------- ### Test Trained CosPlace Model Source: https://github.com/gmberton/cosplace/blob/main/README.md Evaluate a trained CosPlace model. Ensure you provide the correct backbone, output dimension, and the path to your saved model checkpoint. ```bash python3 eval.py --backbone ResNet50 --fc_output_dim 128 --resume_model path/to/best_model.pth ``` -------------------------------- ### GeM Layer for Feature Map Pooling Source: https://context7.com/gmberton/cosplace/llms.txt Demonstrates standalone usage of the GeM layer for pooling feature maps and its integration into a full aggregation pipeline. The GeM layer interpolates between average and max pooling. ```python import torch from cosplace_model.layers import GeM, L2Norm, Flatten # Standalone usage on a feature map from a CNN backbone feature_map = torch.randn(4, 2048, 16, 16) # batch=4, channels=2048, spatial=16×16 gem = GeM(p=3, eps=1e-6) pooled = gem(feature_map) print(pooled.shape) # torch.Size([4, 2048, 1, 1]) print(repr(gem)) # GeM(p=3.0000, eps=1e-06) # Full aggregation pipeline as used inside GeoLocalizationNet aggregation = torch.nn.Sequential( L2Norm(), GeM(), Flatten(), torch.nn.Linear(2048, 512), L2Norm() ) descriptor = aggregation(feature_map) print(descriptor.shape) # torch.Size([4, 512]) ``` -------------------------------- ### Load Trained Model from PyTorch Hub Source: https://github.com/gmberton/cosplace/blob/main/README.md Use this snippet to load a trained model directly from PyTorch Hub without cloning the repository. Specify the desired backbone and the output dimensionality of the fully connected layer. ```python import torch model = torch.hub.load("gmberton/cosplace", "get_trained_model", backbone="ResNet50", fc_output_dim=2048) ``` -------------------------------- ### Save Retrieval Visualization Images Source: https://context7.com/gmberton/cosplace/llms.txt Saves JPEG strips showing query images and their predictions, bordered by color to indicate correctness. Companion .txt files list relevant paths. Set `save_only_wrong_preds` to True to only save visualizations for queries where the top prediction is incorrect. ```python import numpy as np import visualizations from datasets.test_dataset import TestDataset eval_ds = TestDataset( dataset_folder="path/to/sf_xl/processed/test", queries_folder="queries_v1", positive_dist_threshold=25, ) # predictions: array of shape [num_queries, num_preds_to_save] # Each row contains database indices returned by FAISS search predictions = np.array([[102, 45, 301], [88, 12, 200]]) # 2 queries, top-3 preds visualizations.save_preds( predictions=predictions, eval_ds=eval_ds, output_folder="logs/my_experiment/2024-01-01_12-00-00", save_only_wrong_preds=True # only save queries where top-1 prediction is wrong ) # Saves: # logs/.../preds/000.jpg — query + top-3 predictions with green/red borders # logs/.../preds/000.txt — paths of query, predictions, and ground-truth positives ``` -------------------------------- ### Visualize Only Wrong CosPlace Predictions Source: https://github.com/gmberton/cosplace/blob/main/README.md Optimize prediction visualization by saving only the wrongly predicted queries. This focuses on the most interesting failure cases for analysis. ```bash python3 eval.py --backbone ResNet50 --fc_output_dim 512 --resume_model path/to/best_model.pth --save_only_wrong_preds --exp_name=cosplace_on_stlucia ``` -------------------------------- ### Visualize CosPlace Predictions Source: https://github.com/gmberton/cosplace/blob/main/README.md Visualize a specified number of predictions for a trained model. This helps in understanding model performance and identifying failure cases. Predictions are saved in the logs directory. ```bash python3 eval.py --backbone ResNet50 --fc_output_dim 512 --resume_model path/to/best_model.pth --num_preds_to_save=3 --exp_name=cosplace_on_stlucia ``` -------------------------------- ### test.test Source: https://context7.com/gmberton/cosplace/llms.txt Computes Recall@K metrics for the given evaluation dataset and model. ```APIDOC ## test.test(args, eval_ds, model, num_preds_to_save) ### Description Computes Recall@K metrics by extracting descriptors, building a FAISS index, retrieving nearest neighbors, and calculating recall values. Optionally saves prediction images. ### Parameters - **args**: Namespace object containing configuration parameters. - **eval_ds**: The evaluation dataset object (e.g., an instance of `TestDataset`). - **model**: The trained model to use for descriptor extraction. - **num_preds_to_save** (int): Number of prediction images to save for inspection. ### Returns - **recalls**: A dictionary containing Recall@K metrics. - **recalls_str**: A formatted string of the recall metrics. ### Example ```python import torch import argparse import test from cosplace_model import cosplace_network from datasets.test_dataset import TestDataset args = argparse.Namespace( device="cuda", fc_output_dim=512, infer_batch_size=16, num_workers=4, num_preds_to_save=3, save_only_wrong_preds=False, output_folder="logs/my_experiment/2024-01-01_00-00-00", positive_dist_threshold=25, image_size=512, resize_test_imgs=False, ) model = cosplace_network.GeoLocalizationNet("ResNet50", args.fc_output_dim) model.load_state_dict(torch.load("best_model.pth")) model = model.to(args.device) test_ds = TestDataset( dataset_folder="path/to/sf_xl/processed/test", queries_folder="queries_v1", positive_dist_threshold=args.positive_dist_threshold, ) recalls, recalls_str = test.test(args, test_ds, model, num_preds_to_save=3) print(recalls_str) ``` ``` -------------------------------- ### Forward Pass with CosPlace Model Source: https://context7.com/gmberton/cosplace/llms.txt Performs a forward pass through the classifier using normalized descriptors and class labels. Requires a pre-initialized model, criterion, and optimizer. ```python descriptors = torch.randn(32, 512, device="cuda") descriptors = torch.nn.functional.normalize(descriptors, p=2, dim=1) labels = torch.randint(0, 12450, (32,), device="cuda") optimizer.zero_grad() logits = classifier(descriptors, labels) # shape: [32, 12450] loss = criterion(logits, labels) loss.backward() optimizer.step() print(f"Loss: {loss.item():.4f}") # e.g. Loss: 9.4231 ``` -------------------------------- ### TrainDataset Source: https://context7.com/gmberton/cosplace/llms.txt Parses a folder of geo-tagged training images and partitions them into spatial classes for the rotating classifier training scheme. The grouping result is cached on disk for subsequent runs. ```APIDOC ## TrainDataset(args, dataset_folder, M, alpha, N, L, current_group, min_images_per_class) ### Description CosPlace group dataset. Parses a folder of geo-tagged training images (filename contains `@utm_east@utm_north@...@heading@...`), partitions them into spatial classes (M-meter grid cells × alpha-degree heading bins), and organizes classes into non-overlapping groups for the rotating classifier training scheme. The grouping result is cached on disk for subsequent runs. ### Parameters - **args** (object) - Namespace object containing various training arguments. - **dataset_folder** (string) - Path to the folder containing the geo-tagged images. - **M** (int) - Grid cell size in meters for spatial partitioning. - **alpha** (float) - Heading angle bin size in degrees. - **N** (int) - Number of images per class. - **L** (int) - Number of groups. - **current_group** (int) - The current group index to load. - **min_images_per_class** (int) - Minimum number of images required per class. ### Request Example ```python import argparse from datasets.train_dataset import TrainDataset # Minimal args namespace required by TrainDataset args = argparse.Namespace( augmentation_device="cpu", brightness=0.7, contrast=0.7, saturation=0.7, hue=0.5, random_resized_crop=0.5, image_size=512, ) # Example instantiation (assuming dataset_folder, M, alpha, etc. are defined) # dataset = TrainDataset(args, dataset_folder="/path/to/images", M=50, alpha=10, N=10, L=10, current_group=0, min_images_per_class=5) ``` ``` -------------------------------- ### commons.make_deterministic Source: https://context7.com/gmberton/cosplace/llms.txt Seeds all random number generators (RNGs) for reproducibility. This includes Python's `random`, NumPy, and PyTorch CPU/GPU, and disables cuDNN non-determinism. ```APIDOC ## commons.make_deterministic(seed) ### Description Seeds all RNGs for reproducibility. Sets seeds for Python `random`, NumPy, PyTorch CPU/GPU, and disables cuDNN non-determinism. Pass `seed=-1` to skip determinism (useful for maximum GPU throughput in production). ### Parameters - **seed** (integer) - The seed value to use for RNGs. Use `-1` to skip determinism. ### Usage ```python from commons import make_deterministic make_deterministic(seed=0) # Equivalent to: # random.seed(0) # np.random.seed(0) # torch.manual_seed(0) # torch.cuda.manual_seed_all(0) # torch.backends.cudnn.deterministic = True # torch.backends.cudnn.benchmark = False # Skip for faster (non-deterministic) training: make_deterministic(seed=-1) ``` ``` -------------------------------- ### Assign Class and Group IDs using TrainDataset Source: https://context7.com/gmberton/cosplace/llms.txt Utilizes the static method `get__class_id__group_id` to deterministically map UTM coordinates and heading to a class ID and group ID. This is useful for understanding how images are categorized within the dataset's structure. ```python from datasets.train_dataset import TrainDataset # Example: an image at UTM (551300.0, 4180250.0) facing 127 degrees class_id, group_id = TrainDataset.get__class_id__group_id( utm_east=551300.0, utm_north=4180250.0, heading=127.0, M=10, alpha=30, N=5, L=2 ) print(class_id) # (551300, 4180250, 120) — rounded cell + heading bin print(group_id) # (0, 0, 0) — position within the group grid ``` -------------------------------- ### GeoLocalizationNet Source: https://context7.com/gmberton/cosplace/llms.txt The core neural network model for geo-localization. It wraps a torchvision backbone with a GeM pooling aggregation head, L2 normalization, a linear projection, and a final L2 normalization to produce fixed-length, unit-normalized image descriptors. ```APIDOC ## GeoLocalizationNet(backbone, fc_output_dim, train_all_layers) ### Description Core model for geo-localization that wraps a torchvision backbone (ResNet, VGG-16, or EfficientNet) with a GeM pooling aggregation head, an L2 normalization layer, a linear projection, and a final L2 normalization to produce fixed-length, unit-normalized image descriptors suitable for nearest-neighbor retrieval. ### Parameters - **backbone** (string) - The backbone architecture to use (e.g., "ResNet50"). - **fc_output_dim** (int) - The dimensionality of the output descriptors. - **train_all_layers** (bool) - Whether to train all layers or freeze earlier ones. ### Request Example ```python import torch from cosplace_model import cosplace_network # Build a ResNet-50 model with 512-dim descriptors, training only the last two blocks model = cosplace_network.GeoLocalizationNet( backbone="ResNet50", fc_output_dim=512, train_all_layers=False # freeze layers before conv_3 ) model = model.to("cuda").eval() # Run inference on a single normalized image tensor import torchvision.transforms as T from PIL import Image transform = T.Compose([ T.Resize(512), T.CenterCrop(512), T.ToTensor(), T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) img = transform(Image.open("query.jpg").convert("RGB")).unsqueeze(0).to("cuda") with torch.no_grad(): descriptor = model(img) # shape: [1, 512] print(descriptor.shape) # torch.Size([1, 512]) print(descriptor.norm(dim=1)) # tensor([1.0000]) — unit-normalized ``` ``` -------------------------------- ### Make RNGs Deterministic for Reproducibility Source: https://context7.com/gmberton/cosplace/llms.txt Seeds all random number generators (Python, NumPy, PyTorch) and disables cuDNN non-determinism. Set `seed=-1` to skip determinism for maximum GPU throughput. ```python from commons import make_deterministic make_deterministic(seed=0) # Equivalent to: # random.seed(0) # np.random.seed(0) # torch.manual_seed(0) # torch.cuda.manual_seed_all(0) # torch.backends.cudnn.deterministic = True # torch.backends.cudnn.benchmark = False # Skip for faster (non-deterministic) training: make_deterministic(seed=-1) ``` -------------------------------- ### GeM Layer Source: https://context7.com/gmberton/cosplace/llms.txt The GeM (Generalized Mean Pooling) layer is a learnable pooling layer that interpolates between average and max pooling. It's used in the aggregation head of GeoLocalizationNet. ```APIDOC ## GeM Layer ### Description A learnable pooling layer used in the aggregation head of `GeoLocalizationNet`. The power parameter `p` is trained via back-propagation, allowing the model to interpolate between average pooling (p=1) and max pooling (p→∞). Initialized to p=3. ### Usage ```python import torch from cosplace_model.layers import GeM, L2Norm, Flatten # Standalone usage on a feature map from a CNN backbone feature_map = torch.randn(4, 2048, 16, 16) # batch=4, channels=2048, spatial=16×16 gem = GeM(p=3, eps=1e-6) pooled = gem(feature_map) print(pooled.shape) # torch.Size([4, 2048, 1, 1]) print(repr(gem)) # GeM(p=3.0000, eps=1e-06) # Full aggregation pipeline as used inside GeoLocalizationNet aggregation = torch.nn.Sequential( L2Norm(), GeM(), Flatten(), torch.nn.Linear(2048, 512), L2Norm() ) descriptor = aggregation(feature_map) print(descriptor.shape) # torch.Size([4, 512]) ``` ``` -------------------------------- ### TrainDataset.get__class_id__group_id Source: https://context7.com/gmberton/cosplace/llms.txt A static method to assign class and group IDs to a geo-tagged image based on its UTM coordinates and heading. ```APIDOC ## TrainDataset.get__class_id__group_id(utm_east, utm_north, heading, M, alpha, N, L) ### Description Static method that maps raw UTM coordinates and heading to a deterministic `(class_id, group_id)` pair. `class_id` is a `(easting, northing, heading)` triplet rounded to the nearest M-meter / alpha-degree grid. `group_id` indexes which of the N×N×L groups the class falls into. ### Parameters - **utm_east** (float): Easting coordinate. - **utm_north** (float): Northing coordinate. - **heading** (float): Heading angle in degrees. - **M** (int): Cell side length in meters. - **alpha** (int): Heading bin size in degrees. - **N** (int): Spatial stride between groups. - **L** (int): Heading stride between groups. ### Returns - **class_id**: A tuple representing the rounded (easting, northing, heading). - **group_id**: A tuple representing the position within the group grid. ### Example ```python from datasets.train_dataset import TrainDataset class_id, group_id = TrainDataset.get__class_id__group_id( utm_east=551300.0, utm_north=4180250.0, heading=127.0, M=10, alpha=30, N=5, L=2 ) ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.