Spaces:
Sleeping
Sleeping
Debug: Issue with prediction
Browse files- app.py +45 -32
- inference.py +65 -54
app.py
CHANGED
@@ -17,23 +17,34 @@ def load_model(model_path: str):
|
|
17 |
"""
|
18 |
Load the model.
|
19 |
"""
|
20 |
-
# Check if CUDA is available and set device
|
21 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
22 |
print(f"Using device: {device}")
|
23 |
|
24 |
-
# Load the
|
25 |
-
model = models.resnet50(weights=
|
26 |
model = model.to(device)
|
27 |
|
28 |
-
# Load custom weights
|
29 |
state_dict = torch.load(model_path, map_location=device)
|
30 |
-
|
31 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
filtered_state_dict = {k: v for k, v in state_dict['model_state_dict'].items() if k in model.state_dict()}
|
33 |
-
|
34 |
-
|
35 |
model.load_state_dict(filtered_state_dict, strict=False)
|
36 |
model.eval()
|
|
|
|
|
|
|
|
|
|
|
37 |
return model
|
38 |
|
39 |
|
@@ -41,8 +52,8 @@ def load_classes():
|
|
41 |
"""
|
42 |
Load the classes.
|
43 |
"""
|
44 |
-
#
|
45 |
-
weights = models.ResNet50_Weights.
|
46 |
classes = weights.meta["categories"]
|
47 |
return classes
|
48 |
|
@@ -53,7 +64,7 @@ def inference_wrapper(image, alpha, top_k, target_layer):
|
|
53 |
"""
|
54 |
try:
|
55 |
if image is None:
|
56 |
-
return {"
|
57 |
|
58 |
results = inference(
|
59 |
image,
|
@@ -65,19 +76,21 @@ def inference_wrapper(image, alpha, top_k, target_layer):
|
|
65 |
)
|
66 |
|
67 |
if results is None:
|
68 |
-
return {"
|
69 |
|
70 |
return results
|
71 |
|
72 |
-
except
|
73 |
error_msg = str(e)
|
74 |
print(f"Error in inference: {error_msg}")
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
|
80 |
-
|
|
|
|
|
81 |
return {"Error: " + error_msg: 1.0}, None
|
82 |
|
83 |
|
@@ -166,12 +179,12 @@ def main():
|
|
166 |
|
167 |
# Examples section for Gradio 5.x
|
168 |
examples = [
|
169 |
-
[
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
],
|
175 |
[
|
176 |
"assets/examples/cat.jpg",
|
177 |
0.5,
|
@@ -190,12 +203,12 @@ def main():
|
|
190 |
3,
|
191 |
4
|
192 |
],
|
193 |
-
[
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
],
|
199 |
[
|
200 |
"assets/examples/car.jpg",
|
201 |
0.5,
|
@@ -241,14 +254,14 @@ def main():
|
|
241 |
gradcam_output
|
242 |
],
|
243 |
fn=inference_wrapper,
|
244 |
-
cache_examples=
|
245 |
label="Click on any example to run GradCAM"
|
246 |
)
|
247 |
|
248 |
# Queue configuration
|
249 |
-
demo.queue(max_size=1)
|
250 |
|
251 |
-
# Launch
|
252 |
demo.launch(
|
253 |
server_name="0.0.0.0",
|
254 |
server_port=7860,
|
|
|
17 |
"""
|
18 |
Load the model.
|
19 |
"""
|
|
|
20 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
21 |
print(f"Using device: {device}")
|
22 |
|
23 |
+
# Load the model with default weights first
|
24 |
+
model = models.resnet50(weights=models.ResNet50_Weights.IMAGENET1K_V1)
|
25 |
model = model.to(device)
|
26 |
|
27 |
+
# Load custom weights
|
28 |
state_dict = torch.load(model_path, map_location=device)
|
29 |
+
|
30 |
+
# Debug: Print state dict info
|
31 |
+
print("\nState dict keys:", list(state_dict['model_state_dict'].keys())[:5])
|
32 |
+
print("Model state dict keys:", list(model.state_dict().keys())[:5])
|
33 |
+
|
34 |
+
# Check if the final layer weights match
|
35 |
+
fc_weight_shape = state_dict['model_state_dict']['fc.weight'].shape
|
36 |
+
print(f"\nFC layer weight shape: {fc_weight_shape}")
|
37 |
+
|
38 |
filtered_state_dict = {k: v for k, v in state_dict['model_state_dict'].items() if k in model.state_dict()}
|
39 |
+
print(f"Filtered state dict size: {len(filtered_state_dict)} / {len(state_dict['model_state_dict'])}")
|
40 |
+
|
41 |
model.load_state_dict(filtered_state_dict, strict=False)
|
42 |
model.eval()
|
43 |
+
|
44 |
+
# Verify model
|
45 |
+
print("\nModel architecture:")
|
46 |
+
print(model)
|
47 |
+
|
48 |
return model
|
49 |
|
50 |
|
|
|
52 |
"""
|
53 |
Load the classes.
|
54 |
"""
|
55 |
+
# Load classes from the same weights version as the model was trained with
|
56 |
+
weights = models.ResNet50_Weights.IMAGENET1K_V1 # Try V1 instead of V2
|
57 |
classes = weights.meta["categories"]
|
58 |
return classes
|
59 |
|
|
|
64 |
"""
|
65 |
try:
|
66 |
if image is None:
|
67 |
+
return {"Error": 1.0}, None
|
68 |
|
69 |
results = inference(
|
70 |
image,
|
|
|
76 |
)
|
77 |
|
78 |
if results is None:
|
79 |
+
return {"Error": 1.0}, None
|
80 |
|
81 |
return results
|
82 |
|
83 |
+
except RuntimeError as e:
|
84 |
error_msg = str(e)
|
85 |
print(f"Error in inference: {error_msg}")
|
86 |
|
87 |
+
if "out of memory" in error_msg.lower():
|
88 |
+
return {"GPU Memory Error - Please try again": 1.0}, None
|
89 |
+
return {"Runtime Error: " + error_msg: 1.0}, None
|
90 |
|
91 |
+
except Exception as e:
|
92 |
+
error_msg = str(e)
|
93 |
+
print(f"Error in inference: {error_msg}")
|
94 |
return {"Error: " + error_msg: 1.0}, None
|
95 |
|
96 |
|
|
|
179 |
|
180 |
# Examples section for Gradio 5.x
|
181 |
examples = [
|
182 |
+
# [
|
183 |
+
# "assets/examples/dog.jpg",
|
184 |
+
# 0.5, # alpha slider
|
185 |
+
# 3, # top_k slider
|
186 |
+
# 4 # target_layer slider
|
187 |
+
# ],
|
188 |
[
|
189 |
"assets/examples/cat.jpg",
|
190 |
0.5,
|
|
|
203 |
3,
|
204 |
4
|
205 |
],
|
206 |
+
# [
|
207 |
+
# "assets/examples/shark-plane.jpg",
|
208 |
+
# 0.5,
|
209 |
+
# 3,
|
210 |
+
# 4
|
211 |
+
# ],
|
212 |
[
|
213 |
"assets/examples/car.jpg",
|
214 |
0.5,
|
|
|
254 |
gradcam_output
|
255 |
],
|
256 |
fn=inference_wrapper,
|
257 |
+
cache_examples=False, # Disable caching to prevent memory issues
|
258 |
label="Click on any example to run GradCAM"
|
259 |
)
|
260 |
|
261 |
# Queue configuration
|
262 |
+
demo.queue(max_size=1) # Only allow one job at a time
|
263 |
|
264 |
+
# Launch with minimal memory usage
|
265 |
demo.launch(
|
266 |
server_name="0.0.0.0",
|
267 |
server_port=7860,
|
inference.py
CHANGED
@@ -23,76 +23,87 @@ def inference(image, alpha, top_k, target_layer, model=None, classes=None):
|
|
23 |
Run inference with GradCAM visualization
|
24 |
"""
|
25 |
try:
|
|
|
|
|
|
|
|
|
26 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
27 |
|
28 |
# Ensure model is on correct device and in eval mode
|
29 |
model = model.to(device)
|
30 |
model.eval()
|
31 |
|
32 |
-
#
|
33 |
-
|
|
|
|
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
|
72 |
-
|
73 |
-
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
if torch.cuda.is_available():
|
93 |
torch.cuda.empty_cache()
|
94 |
-
|
95 |
-
return show_confidences, visualization
|
96 |
|
97 |
except Exception as e:
|
98 |
if torch.cuda.is_available():
|
|
|
23 |
Run inference with GradCAM visualization
|
24 |
"""
|
25 |
try:
|
26 |
+
# Clear CUDA cache before starting
|
27 |
+
if torch.cuda.is_available():
|
28 |
+
torch.cuda.empty_cache()
|
29 |
+
|
30 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
31 |
|
32 |
# Ensure model is on correct device and in eval mode
|
33 |
model = model.to(device)
|
34 |
model.eval()
|
35 |
|
36 |
+
# Process with reduced precision to save memory
|
37 |
+
with torch.cuda.amp.autocast():
|
38 |
+
# Save a copy of input img
|
39 |
+
org_img = image.copy()
|
40 |
|
41 |
+
# Convert img to tensor and normalize it
|
42 |
+
_transform = transforms.Compose([
|
43 |
+
transforms.ToTensor(),
|
44 |
+
transforms.Normalize(
|
45 |
+
mean=[0.485, 0.456, 0.406],
|
46 |
+
std=[0.229, 0.224, 0.225]
|
47 |
+
)
|
48 |
+
])
|
49 |
|
50 |
+
# Preprocess the input image and move to device
|
51 |
+
input_tensor = _transform(image).to(device)
|
52 |
+
input_tensor = input_tensor.unsqueeze(0)
|
53 |
+
input_tensor.requires_grad = True
|
54 |
+
|
55 |
+
# Get Model Predictions
|
56 |
+
outputs = model(input_tensor)
|
57 |
+
probabilities = torch.softmax(outputs, dim=1)[0]
|
58 |
+
confidences = {classes[i]: float(probabilities[i]) for i in range(1000)}
|
59 |
|
60 |
+
# Select the top classes based on user input
|
61 |
+
sorted_confidences = sorted(confidences.items(), key=lambda val: val[1], reverse=True)
|
62 |
+
show_confidences = OrderedDict(sorted_confidences[:top_k])
|
63 |
|
64 |
+
# Map layer numbers to meaningful parts of the ResNet architecture
|
65 |
+
_layers = {
|
66 |
+
1: model.conv1,
|
67 |
+
2: model.layer1[-1],
|
68 |
+
3: model.layer2[-1],
|
69 |
+
4: model.layer3[-1],
|
70 |
+
5: model.layer4[-1],
|
71 |
+
6: model.layer4[-1]
|
72 |
+
}
|
73 |
|
74 |
+
# Ensure valid layer selection
|
75 |
+
target_layer = min(max(target_layer, 1), 6)
|
76 |
+
target_layers = [_layers[target_layer]]
|
77 |
|
78 |
+
# Get the class activations from the selected layer
|
79 |
+
cam = GradCAM(model=model, target_layers=target_layers)
|
80 |
|
81 |
+
# Get the most probable class index
|
82 |
+
top_class = max(confidences.items(), key=lambda x: x[1])[0]
|
83 |
+
class_idx = classes.index(top_class)
|
84 |
+
|
85 |
+
# Generate GradCAM for the top predicted class
|
86 |
+
grayscale_cam = cam(
|
87 |
+
input_tensor=input_tensor,
|
88 |
+
targets=[ClassifierOutputTarget(class_idx)],
|
89 |
+
aug_smooth=False, # Disable augmentation for memory efficiency
|
90 |
+
eigen_smooth=False # Disable eigen smoothing for memory efficiency
|
91 |
+
)
|
92 |
+
grayscale_cam = grayscale_cam[0, :]
|
93 |
|
94 |
+
# Overlay input image with Class activations
|
95 |
+
visualization = show_cam_on_image(org_img/255., grayscale_cam, use_rgb=True, image_weight=alpha)
|
96 |
+
|
97 |
+
# Clear CUDA cache after processing
|
98 |
+
if torch.cuda.is_available():
|
99 |
+
torch.cuda.empty_cache()
|
100 |
+
|
101 |
+
return show_confidences, visualization
|
102 |
+
|
103 |
+
except torch.cuda.OutOfMemoryError:
|
104 |
if torch.cuda.is_available():
|
105 |
torch.cuda.empty_cache()
|
106 |
+
raise RuntimeError("GPU out of memory - Please try again with a smaller image")
|
|
|
107 |
|
108 |
except Exception as e:
|
109 |
if torch.cuda.is_available():
|