Views
No views yet
| Model | Boyut | Parametre | mAPᵛᵃᴵ | APᵛᵃᴵ | CPU b1 | V100 b1 | V100 b32 |
|---|---|---|---|---|---|---|---|
| Vbai-DPA 2.4f | 224 | 38.68M | %56.66 | %53.80 | 28.8ms | 14.4ms | 3.64ms |
| Vbai-DPA 2.4c | 224 | 77.52M | %62.87 | %60.54 | 40.33ms | 20.16ms | 4.03ms |
| Vbai-DPA 2.4q | 224 | 131.30M | %82.93 | %87.45 | 85.48ms | 42.74ms | 8.55ms |
| Model | Test Size | Params | mAPᵛᵃᴵ | APᵛᵃᴵ | CPU b1 | V100 b1 | V100 b32 |
|---|---|---|---|---|---|---|---|
| Vbai-DPA 2.4f | 224 | 38.68M | 56.66% | 53.80% | 28.8ms | 14.4ms | 3.64ms |
| Vbai-DPA 2.4c | 224 | 77.52M | 62.87% | 60.54% | 40.33ms | 20.16ms | 4.03ms |
| Vbai-DPA 2.4q | 224 | 131.30M | 82.93% | 87.45% | 85.48ms | 42.74ms | 8.55ms |
1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4
5
6class CBAMAttentionCheckpoint(nn.Module):
7 def __init__(self, channels, reduction=8):
8 super(CBAMAttentionCheckpoint, self).__init__()
9
10 # Channel attention (using Conv2d 1x1 as in checkpoint, NO BIAS)
11 reduced_channels = max(channels // reduction, 1)
12 self.channel_attention = nn.Sequential(
13 nn.Conv2d(channels, reduced_channels, 1, bias=False),
14 nn.ReLU(),
15 nn.Conv2d(reduced_channels, channels, 1, bias=False),
16 )
17
18 # Spatial attention (7x7 conv as in checkpoint, NO BIAS)
19 self.spatial_attention = nn.Sequential(
20 nn.Conv2d(2, 1, 7, padding=3, bias=False),
21 )
22
23 def forward(self, x):
24 avg_pool = F.adaptive_avg_pool2d(x, 1)
25 max_pool = F.adaptive_max_pool2d(x, 1)
26
27 avg_out = self.channel_attention(avg_pool)
28 max_out = self.channel_attention(max_pool)
29
30 channel_att = torch.sigmoid(avg_out + max_out)
31 x = x * channel_att
32
33 avg_out = torch.mean(x, dim=1, keepdim=True)
34 max_out, _ = torch.max(x, dim=1, keepdim=True)
35 spatial_in = torch.cat([avg_out, max_out], dim=1)
36
37 spatial_att = torch.sigmoid(self.spatial_attention(spatial_in))
38 x = x * spatial_att
39
40 return x
41
42
43class CheckpointVbaiDPA24(nn.Module):
44 def __init__(self, model_type='f', num_classes=6):
45 super(CheckpointVbaiDPA24, self).__init__()
46
47 self.model_type = model_type
48 self.num_classes = num_classes
49
50 # Conv layers: Sequential with Conv+BN+ReLU+Pool pattern
51 if model_type == 'f':
52 self.conv_layers = nn.Sequential(
53 nn.Conv2d(3, 16, 3, padding=1),
54 nn.BatchNorm2d(16),
55 nn.ReLU(),
56 nn.MaxPool2d(2, 2),
57 nn.Conv2d(16, 32, 3, padding=1),
58 nn.BatchNorm2d(32),
59 nn.ReLU(),
60 nn.MaxPool2d(2, 2),
61 nn.Conv2d(32, 64, 3, padding=1),
62 nn.BatchNorm2d(64),
63 nn.ReLU(),
64 nn.MaxPool2d(2, 2),
65 )
66 self.attention_modules = nn.ModuleList([
67 CBAMAttentionCheckpoint(16, reduction=8),
68 CBAMAttentionCheckpoint(32, reduction=8),
69 CBAMAttentionCheckpoint(64, reduction=8),
70 ])
71 fc_input = 64 * 28 * 28
72 fc_sizes = [256, 128, 6]
73
74 elif model_type == 'c':
75 self.conv_layers = nn.Sequential(
76 nn.Conv2d(3, 32, 3, padding=1),
77 nn.BatchNorm2d(32),
78 nn.ReLU(),
79 nn.MaxPool2d(2, 2),
80 nn.Conv2d(32, 64, 3, padding=1),
81 nn.BatchNorm2d(64),
82 nn.ReLU(),
83 nn.MaxPool2d(2, 2),
84 nn.Conv2d(64, 128, 3, padding=1),
85 nn.BatchNorm2d(128),
86 nn.ReLU(),
87 nn.MaxPool2d(2, 2),
88 )
89 self.attention_modules = nn.ModuleList([
90 CBAMAttentionCheckpoint(32, reduction=8),
91 CBAMAttentionCheckpoint(64, reduction=8),
92 CBAMAttentionCheckpoint(128, reduction=8),
93 ])
94 fc_input = 128 * 28 * 28
95 fc_sizes = [512, 256, 6]
96
97 elif model_type == 'q':
98 self.conv_layers = nn.Sequential(
99 nn.Conv2d(3, 64, 3, padding=1),
100 nn.BatchNorm2d(64),
101 nn.ReLU(),
102 nn.MaxPool2d(2, 2),
103 nn.Conv2d(64, 128, 3, padding=1),
104 nn.BatchNorm2d(128),
105 nn.ReLU(),
106 nn.MaxPool2d(2, 2),
107 nn.Conv2d(128, 256, 3, padding=1),
108 nn.BatchNorm2d(256),
109 nn.ReLU(),
110 nn.MaxPool2d(2, 2),
111 nn.Conv2d(256, 512, 3, padding=1),
112 nn.BatchNorm2d(512),
113 nn.ReLU(),
114 nn.MaxPool2d(2, 2),
115 )
116 self.attention_modules = nn.ModuleList([
117 CBAMAttentionCheckpoint(64, reduction=8),
118 CBAMAttentionCheckpoint(128, reduction=8),
119 CBAMAttentionCheckpoint(256, reduction=8),
120 CBAMAttentionCheckpoint(512, reduction=8),
121 ])
122 fc_input = 512 * 14 * 14
123 fc_sizes = [1024, 512, 6]
124
125 # Edge detection branch
126 self.edge_conv1 = nn.Conv2d(1, 32, 3, padding=1)
127 self.edge_conv2 = nn.Conv2d(32, 64, 3, padding=1)
128 # Edge fc input size depends on pooling
129 self.edge_fc = nn.Linear(64 * 56 * 56, 128)
130
131 # Main classifier
132 self.classifier = nn.Sequential(
133 nn.Linear(fc_input, fc_sizes[0]),
134 nn.ReLU(),
135 nn.Dropout(0.5),
136 nn.Linear(fc_sizes[0], fc_sizes[1]),
137 nn.ReLU(),
138 nn.Dropout(0.5),
139 nn.Linear(fc_sizes[1], fc_sizes[2]),
140 )
141
142 # Combined classifier (with edge features)
143 self.combined_classifier = nn.Sequential(
144 nn.Linear(fc_sizes[0] + 128, fc_sizes[0]),
145 nn.ReLU(),
146 nn.Dropout(0.5),
147 nn.Linear(fc_sizes[0], fc_sizes[2]),
148 )
149
150 def forward(self, x, edge_x=None):
151 if self.model_type == 'f' or self.model_type == 'c':
152 x = self.conv_layers[0:4](x)
153 x = self.attention_modules[0](x)
154
155 x = self.conv_layers[4:8](x)
156 x = self.attention_modules[1](x)
157
158 x = self.conv_layers[8:12](x)
159 x = self.attention_modules[2](x)
160 attention_map = x
161
162 elif self.model_type == 'q':
163 x = self.conv_layers[0:4](x)
164 x = self.attention_modules[0](x)
165
166 x = self.conv_layers[4:8](x)
167 x = self.attention_modules[1](x)
168
169 x = self.conv_layers[8:12](x)
170 x = self.attention_modules[2](x)
171
172 x = self.conv_layers[12:16](x)
173 x = self.attention_modules[3](x)
174 attention_map = x
175
176 x = x.view(x.size(0), -1)
177
178 x = self.classifier[0](x)
179 x = self.classifier[1](x)
180 features = self.classifier[2](x)
181
182 if edge_x is not None:
183 try:
184 edge_x = F.relu(self.edge_conv1(edge_x))
185 edge_x = F.max_pool2d(edge_x, 2, 2)
186
187 edge_x = F.relu(self.edge_conv2(edge_x))
188 edge_x = F.max_pool2d(edge_x, 2, 2)
189
190 edge_features = edge_x.view(edge_x.size(0), -1)
191 edge_features = self.edge_fc(edge_features)
192
193 combined = torch.cat([features, edge_features], dim=1)
194 output = self.combined_classifier(combined)
195 except Exception as e:
196 output = self.classifier[3:](features)
197 else:
198 output = self.classifier[3:](features)
199
200 return output, attention_mapimport os
import torch
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget
from checkpoint_model import CheckpointVbaiDPA24
TEST_IMAGE = "test/image/path"
MODEL = 'c' # Model type | f => fast, c => classic, q => quality
MODEL_PATHS = {
'f': 'Vbai-DPA 2.4f.pt/model/path',
'c': 'Vbai-DPA 2.4c.pt/model/path',
'q': 'Vbai-DPA 2.4q.pt/model/path',
}
CLASS_NAMES = [
'AD Alzheimer Diseases',
'AD Mild Demented',
'AD Moderate Demented',
'AD Very Mild Demented',
'CN Non Demented',
'PD Parkinson Diseases'
]
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])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor(),
])
def detect_brain_edges(edge_tensor):
edge_np = edge_tensor.squeeze().cpu().numpy()
edge_np = ((edge_np - edge_np.min()) / (edge_np.max() - edge_np.min() + 1e-8) * 255).astype(np.uint8)
edges = cv2.Canny(edge_np, 50, 150)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
edges_closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
contours, _ = cv2.findContours(edges_closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
return edges, contours
def main():
print("\n" + "="*70)
print("Vbai-DPA 2.4")
print("="*70)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"✓ Device: {device}")
print(f"✓ Loading model: Vbai-DPA 2.4{MODEL.upper()}")
model = CheckpointVbaiDPA24(model_type=MODEL, num_classes=6).to(device)
checkpoint = torch.load(MODEL_PATHS[MODEL], map_location=device, weights_only=False)
model.load_state_dict(checkpoint.get('model_state_dict', checkpoint))
model.eval()
target_layer = model.conv_layers[12] if MODEL == 'q' else model.conv_layers[8]
cam = GradCAM(model=model, target_layers=[target_layer])
print(f"✓ Loading image: {os.path.basename(TEST_IMAGE)}")
img = Image.open(TEST_IMAGE).convert('RGB')
inp = transform(img).unsqueeze(0).to(device)
edge_tensor = edge_transform(img).unsqueeze(0).to(device)
print(f"✓ Prediction...")
with torch.no_grad():
output, attention_map = model(inp, edge_tensor)
probs = F.softmax(output, dim=1)
pred = output.argmax(1).item()
conf = probs[0, pred].item() * 100
top3_probs, top3_indices = torch.topk(probs[0], 3)
print("\n" + "="*70)
print("RESULTS:")
print("="*70)
print(f"✓ Main Pred: {CLASS_NAMES[pred]}")
print(f"✓ Confidence Score: {conf:.2f}%")
print(f"\nTop-3 Predictions:")
for i, (idx, prob) in enumerate(zip(top3_indices, top3_probs), 1):
print(f" {i}. {CLASS_NAMES[idx.item()]}: {prob.item()*100:.2f}%")
print("="*70)
print(f"\n✓ Analysing brain structure...")
edges, contours = detect_brain_edges(edge_tensor)
print(f"✓ Calculating Grad-CAM...")
cam_mask = cam(input_tensor=inp, targets=[ClassifierOutputTarget(pred)])[0]
cam_mask = np.squeeze(cam_mask)
att_np = attention_map[0].mean(0).cpu().numpy()
att_np = (att_np - att_np.min()) / (att_np.max() - att_np.min() + 1e-8)
att_np = cv2.resize(att_np, (224, 224))
print(f"✓ Creating visualization...")
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
axes[0, 0].imshow(img)
axes[0, 0].set_title('Original MRI', fontsize=14, fontweight='bold')
axes[0, 0].axis('off')
axes[0, 1].imshow(edges, cmap='gray')
axes[0, 1].set_title('Brain Edges', fontsize=14, fontweight='bold')
axes[0, 1].axis('off')
img_contours = np.array(img.resize((224, 224)))
img_contours = cv2.cvtColor(img_contours, cv2.COLOR_RGB2BGR)
if contours:
cv2.drawContours(img_contours, contours, -1, (0, 255, 0), 2)
for i, cnt in enumerate(contours):
M = cv2.moments(cnt)
if M['m00'] != 0:
cx, cy = int(M['m10']/M['m00']), int(M['m01']/M['m00'])
cv2.circle(img_contours, (cx, cy), 5, (255, 0, 0), -1)
cv2.putText(img_contours, f"{i+1}", (cx+10, cy),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
img_contours = cv2.cvtColor(img_contours, cv2.COLOR_BGR2RGB)
axes[0, 2].imshow(img_contours)
axes[0, 2].set_title('Brain Structure Signs', fontsize=14, fontweight='bold')
axes[0, 2].axis('off')
im = axes[1, 0].imshow(att_np, cmap='hot')
axes[1, 0].set_title('Attention Map', fontsize=14, fontweight='bold')
axes[1, 0].axis('off')
plt.colorbar(im, ax=axes[1, 0], fraction=0.046)
im2 = axes[1, 1].imshow(cam_mask, cmap='jet')
axes[1, 1].set_title('Grad-CAM', fontsize=14, fontweight='bold')
axes[1, 1].axis('off')
plt.colorbar(im2, ax=axes[1, 1], fraction=0.046)
rgb_np = inp[0].permute(1, 2, 0).cpu().numpy()
rgb_np = (rgb_np - rgb_np.min()) / (rgb_np.max() - rgb_np.min())
cam_colored = cv2.applyColorMap(np.uint8(cam_mask * 255), cv2.COLORMAP_JET)
cam_colored = cv2.cvtColor(cam_colored, cv2.COLOR_BGR2RGB) / 255.0
overlay = cam_colored * 0.5 + rgb_np * 0.5
overlay = np.clip(overlay, 0, 1)
axes[1, 2].imshow(overlay)
axes[1, 2].set_title(f'Prediction: {CLASS_NAMES[pred]}\nConfidence: {conf:.1f}%',
fontsize=14, fontweight='bold')
axes[1, 2].axis('off')
fig.suptitle(f'Vbai-DPA 2.4{MODEL.upper()} - {os.path.basename(TEST_IMAGE)}',
fontsize=16, fontweight='bold', y=0.98)
plt.tight_layout()
output_file = f'quick_test_result_{MODEL}.png'
plt.savefig(output_file, dpi=150, bbox_inches='tight')
print(f"✓ Results saved: {output_file}")
plt.show()
print("\n✓ Test Completed!")
print("="*70 + "\n")
if __name__ == '__main__':
try:
main()
except Exception as e:
print(f"\n✗ ERROR: {str(e)}")
import traceback
traceback.print_exc()