You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

Custom Xception Model

This is a fine-tuned Xception model's ensemble for predicting latitude and longitude from images.

Model Metadata

  • Latitude Mean: 39.95165153939056
  • Latitude Std: 0.0007248140892687559
  • Longitude Mean: -75.19139496469714
  • Longitude Std: 0.0007013685468922234

Error Metrics

  • Mean Absolute Error (MAE): 0.00020775681686579616
  • Root Mean Squared Error (RMSE): 0.0003053099508331751

Model Evaluation

import torch
from transformers import AutoImageProcessor, AutoModelForImageClassification
from huggingface_hub import hf_hub_download, login
import torch.nn as nn
from datasets import load_dataset
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, Dataset
import numpy as np
from geopy.distance import geodesic
from timm import create_model


login(token="")


class CustomXceptionModel(nn.Module):
    def __init__(self, model_name="legacy_xception", num_classes=2, metadata=None):
        super().__init__()

        self.metadata = metadata if metadata is not None else {}
        self.xception = create_model(model_name, pretrained=False)
        in_features = self.xception.fc.in_features

        self.xception.fc = nn.Linear(in_features, 2)

    def forward(self, x):
        return self.xception(x)


model_path = hf_hub_download(repo_id="aaaimg2gps/ensemble", filename="best_bagging_models.pth")
model_list = torch.load(model_path)
for i in range(len(model_list)):
    model_list[i] = model_list[i].to(torch.device("cuda" if torch.cuda.is_available() else "cpu"))


lat_mean = 39.95165153939056
lat_std = 0.0007248140892687559
lon_mean = -75.19139496469714
lon_std = 0.0007013685468922234

#test dataset
dataset_test = load_dataset("gydou/released_img", split="train")

inference_transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

class GPSImageDataset(Dataset):
    def __init__(self, hf_dataset, transform=None, lat_mean=None, lat_std=None, lon_mean=None, lon_std=None):
        self.hf_dataset = hf_dataset
        self.transform = transform
        self.latitude_mean = lat_mean
        self.latitude_std = lat_std
        self.longitude_mean = lon_mean
        self.longitude_std = lon_std

    def __len__(self):
        return len(self.hf_dataset)

    def __getitem__(self, idx):
        example = self.hf_dataset[idx]
        image = example['image']
        latitude = example['Latitude']
        longitude = example['Longitude']

        if self.transform:
            image = self.transform(image)

        latitude = (latitude - self.latitude_mean) / self.latitude_std
        longitude = (longitude - self.longitude_mean) / self.longitude_std
        gps_coords = torch.tensor([latitude, longitude], dtype=torch.float32)

        return image, gps_coords

test_dataset = GPSImageDataset(
    hf_dataset=dataset_test,
    transform=inference_transform,
    lat_mean=lat_mean,
    lat_std=lat_std,
    lon_mean=lon_mean,
    lon_std=lon_std
)
test_dataloader = DataLoader(test_dataset, batch_size=32, shuffle=False)

def weighted_mean(outputs_list):
    outputs_stack = torch.stack(outputs_list, dim=0)  # (num_models, batch_size, 2)
    weighted_outputs = []
    epsilon = 1e-6  

    for i in range(outputs_stack.size(1)):  
        sample_preds = outputs_stack[:, i, :]  
        distances = torch.cdist(sample_preds, sample_preds, p=2)  
        avg_distances = distances.mean(dim=1)  
        weights = 1 / (avg_distances + epsilon)  
        normalized_weights = weights / weights.sum()  
        weighted_output = (sample_preds * normalized_weights[:, None]).sum(dim=0)
        weighted_outputs.append(weighted_output)

    return torch.stack(weighted_outputs, dim=0)

def evaluate_model(model_list, dataloader, device):
    distances = []

    with torch.no_grad():
        for images, gps_coords in dataloader:
            images = images.to(device)
            gps_coords = gps_coords.to(device)

            # prediction of each model
            outputs_list = [model(images) for model in model_list]

            # weighted mean of predictions
            outputs_mean = weighted_mean(outputs_list)

            # denormalize predictions and actuals
            preds = outputs_mean.cpu() * torch.tensor([lat_std, lon_std]) + torch.tensor([lat_mean, lon_mean])
            actuals = gps_coords.cpu() * torch.tensor([lat_std, lon_std]) + torch.tensor([lat_mean, lon_mean])

            for pred, actual in zip(preds.numpy(), actuals.numpy()):
                distance = geodesic((actual[0], actual[1]), (pred[0], pred[1])).meters
                distances.append(distance)
                print(f"Predicted coordinates: ({pred[0]:.6f}, {pred[1]:.6f})")
                print(f"Actual coordinates: ({actual[0]:.6f}, {actual[1]:.6f})")
                print(f"Distance error: {distance:.2f} meters")
                print("---")

    mean_dist = np.mean(distances)
    median_dist = np.median(distances)
    dist_std = np.std(distances)
    dist_95 = np.percentile(distances, 95)

    print("\n=== Overall Performance Evaluation ===")
    print(f'Mean distance error: {mean_dist:.2f} meters')
    print(f'Median distance error: {median_dist:.2f} meters')
    print(f'Distance standard deviation: {dist_std:.2f} meters')
    print(f'95th percentile distance error: {dist_95:.2f} meters')

# evaluation
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("Starting model evaluation...")
evaluate_model(model_list, test_dataloader, device)
Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support