lling0212 commited on
Commit
d7b8340
·
1 Parent(s): 5e51f5f

Add README file

Browse files
Files changed (1) hide show
  1. readme.md +203 -0
readme.md ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This contains the instruction for running model 2
2
+
3
+ ### Training data mean and std
4
+ lat_mean: 39.95156937654321
5
+ lat_std: 0.0005992518588323268
6
+ lon_mean: -75.19136795987654
7
+ lon_std: 0.0007030395253318959
8
+
9
+
10
+ ### Instruction to run and test the model
11
+
12
+ Relevant imports
13
+ ```python
14
+ from transformers import PretrainedConfig
15
+ import torch.nn as nn
16
+ import torch
17
+ import torchvision.models as models
18
+ import torchvision.transforms as transforms
19
+ from torch.utils.data import DataLoader, Dataset
20
+ from transformers import AutoImageProcessor, AutoModelForImageClassification
21
+ from huggingface_hub import PyTorchModelHubMixin
22
+ from PIL import Image
23
+ import os
24
+ import numpy as np
25
+ from huggingface_hub import hf_hub_download
26
+
27
+ lat_mean = 39.95156937654321
28
+ lat_std = 0.0005992518588323268
29
+ lon_mean = -75.19136795987654
30
+ lon_std = 0.0007030395253318959
31
+ ```
32
+
33
+ Our model uses the CustomModel class. To use the model, first run the class definition.
34
+ ```python
35
+ from transformers import PretrainedConfig
36
+
37
+ class CustomResNetConfig(PretrainedConfig):
38
+ model_type = "custom-resnet"
39
+
40
+ def __init__(self, num_labels=2, **kwargs):
41
+ super().__init__(**kwargs)
42
+ self.num_labels = num_labels
43
+
44
+ class CustomResNetModel(nn.Module, PyTorchModelHubMixin):
45
+ config_class = CustomResNetConfig
46
+
47
+ def __init__(self, model_name="microsoft/resnet-18",
48
+ num_classes=2,
49
+ train_final_layer_only=False):
50
+ super().__init__()
51
+
52
+ # Load pre-trained ResNet model from Hugging Face
53
+ self.resnet = AutoModelForImageClassification.from_pretrained(model_name)
54
+
55
+ # Access the Linear layer within the Sequential classifier
56
+ in_features = self.resnet.classifier[1].in_features
57
+
58
+ # Modify the classifier layer to have the desired number of output classes
59
+ self.resnet.classifier = nn.Sequential(
60
+ nn.Flatten(),
61
+ nn.Linear(in_features, 128),
62
+ nn.BatchNorm1d(128),
63
+ nn.ReLU(),
64
+ nn.Dropout(p=0.5),
65
+ nn.Linear(128, num_classes)
66
+ )
67
+
68
+ self.config = CustomResNetConfig(num_labels=num_classes)
69
+
70
+ # Freeze previous weights
71
+ if train_final_layer_only:
72
+ for name, param in self.resnet.named_parameters():
73
+ if "classifier" not in name:
74
+ param.requires_grad = False
75
+ else:
76
+ print(f"Unfrozen layer: {name}")
77
+
78
+ def forward(self, x):
79
+ return self.resnet(x)
80
+
81
+ def save_pretrained(self, save_directory, **kwargs):
82
+ """Save model weights and custom configuration in Hugging Face format."""
83
+ os.makedirs(save_directory, exist_ok=True)
84
+
85
+ # Save model weights
86
+ torch.save(self.state_dict(), os.path.join(save_directory, "pytorch_model.bin"))
87
+
88
+ # Save configuration
89
+ self.config.save_pretrained(save_directory)
90
+
91
+ @classmethod
92
+ def from_pretrained(cls, repo_id, model_name="microsoft/resnet-18", **kwargs):
93
+ """Load model weights and configuration from Hugging Face Hub or local directory."""
94
+ # Download pytorch_model.bin from Hugging Face Hub
95
+ model_path = hf_hub_download(repo_id=repo_id, filename="pytorch_model.bin")
96
+
97
+ # Download config.json from Hugging Face Hub
98
+ config_path = hf_hub_download(repo_id=repo_id, filename="config.json")
99
+
100
+ # Load configuration
101
+ config = CustomResNetConfig.from_pretrained(config_path)
102
+
103
+ # Create the model
104
+ model = cls(model_name=model_name, num_classes=config.num_labels)
105
+
106
+ # Load state_dict
107
+ model.load_state_dict(torch.load(model_path, map_location=torch.device("cpu")))
108
+
109
+ return model
110
+
111
+
112
+ ```
113
+
114
+ Then load the model weights from huggingface from our repo.
115
+ ```python
116
+ REPO_MODEL_NAME = "final-project-5190/model-2"
117
+ BACKBONE_MODEL_NAME = "microsoft/resnet-50"
118
+ model=CustomResNetModel.from_pretrained(REPO_MODEL_NAME, model_name=BACKBONE_MODEL_NAME)
119
+ ```
120
+
121
+ Now use the model for inference. Here is an example we ran on the release dataset.
122
+ ```python
123
+ # Load test data
124
+ release_data = load_dataset("gydou/released_img", split="train")
125
+
126
+ # Create dataset and dataloader using training mean and std
127
+ rel_dataset = GPSImageDataset(
128
+ hf_dataset=release_data,
129
+ transform=inference_transform,
130
+ lat_mean=lat_mean,
131
+ lat_std=lat_std,
132
+ lon_mean=lon_mean,
133
+ lon_std=lon_std
134
+ )
135
+ rel_dataloader = DataLoader(rel_dataset, batch_size=32, shuffle=False)
136
+
137
+ # Print MSE and root MSE
138
+ from sklearn.metrics import mean_absolute_error, mean_squared_error
139
+
140
+ # Ensure model is on the correct device
141
+ model = model.to(device)
142
+
143
+ # Initialize lists to store predictions and actual values
144
+ all_preds = []
145
+ all_actuals = []
146
+
147
+ model.eval()
148
+ with torch.no_grad():
149
+ for images, gps_coords in rel_dataloader:
150
+ images, gps_coords = images.to(device), gps_coords.to(device)
151
+
152
+ # Forward pass
153
+ outputs = model(images)
154
+
155
+ # Extract logits (predictions)
156
+ logits = outputs.logits # Use .logits to get the tensor
157
+
158
+ # Denormalize predictions and actual values
159
+ preds = logits.cpu() * torch.tensor([lat_std, lon_std]) + torch.tensor([lat_mean, lon_mean])
160
+ actuals = gps_coords.cpu() * torch.tensor([lat_std, lon_std]) + torch.tensor([lat_mean, lon_mean])
161
+
162
+ all_preds.append(preds)
163
+ all_actuals.append(actuals)
164
+
165
+ # Concatenate all batches
166
+ all_preds = torch.cat(all_preds).numpy()
167
+ all_actuals = torch.cat(all_actuals).numpy()
168
+
169
+ # Compute error metrics
170
+ mae = mean_absolute_error(all_actuals, all_preds)
171
+ rmse = mean_squared_error(all_actuals, all_preds, squared=False)
172
+
173
+ print(f'Release Dataset Mean Absolute Error: {mae}')
174
+ print(f'Release Dataset Root Mean Squared Error: {rmse}')
175
+
176
+ # Convert predictions and actuals to meters
177
+ latitude_mean_radians = np.radians(lat_mean) # Convert to radians for cosine
178
+ meters_per_degree_latitude = 111000 # Constant
179
+ meters_per_degree_longitude = 111000 * np.cos(latitude_mean_radians) # Adjusted for latitude mean
180
+
181
+ all_preds_meters = all_preds.copy()
182
+ all_preds_meters[:, 0] *= meters_per_degree_latitude # Latitude to meters
183
+ all_preds_meters[:, 1] *= meters_per_degree_longitude # Longitude to meters
184
+
185
+ all_actuals_meters = all_actuals.copy()
186
+ all_actuals_meters[:, 0] *= meters_per_degree_latitude # Latitude to meters
187
+ all_actuals_meters[:, 1] *= meters_per_degree_longitude # Longitude to meters
188
+
189
+ # Compute error metrics in meters
190
+ mae_meters = mean_absolute_error(all_actuals_meters, all_preds_meters)
191
+ rmse_meters = mean_squared_error(all_actuals_meters, all_preds_meters, squared=False)
192
+
193
+ print(f"Mean Absolute Error (meters): {mae_meters:.2f}")
194
+ print(f"Root Mean Squared Error (meters): {rmse_meters:.2f}")
195
+ ```
196
+
197
+ After running the inference, the following results are printed -
198
+ ```
199
+ Release Dataset Mean Absolute Error: 0.00046400768003540093
200
+ Release Dataset Root Mean Squared Error: 0.0005684648079729969
201
+ Mean Absolute Error (meters): 45.92
202
+ Root Mean Squared Error (meters): 56.18
203
+ ```