| Model | Test Size | Params | Accuracy | mAPᵛᵃᴵ | F1 Score | Recall | Precision |
|---|---|---|---|---|---|---|---|
| Vbai-2.5f | 224 | 129M | 71.71% | 72.41% | 71.21% | 69.58% | 76.64% |
| Vbai-2.5q | 224 | 220M | 82.44% | 84.40% | 80.95% | 83.99% | 80.08% |
| Vbai-2.5T+ | 224 | 207M | 65.55% | 67.33% | 59.82% | 67.62% | 63.56% |
| Model | Accuracy | mAPᵛᵃᴵ | F1 Score | Recall |
|---|---|---|---|---|
| Vbai-2.5f | 71.71% | 72.41% | 71.21% | 69.58% |
| Vbai-2.5q | 82.44% | 84.40% | 80.95% | 83.99% |
| Vbai-2.5T+ | 35.86% | 35.54% | 24.38% | 40.00% |
| Model | Accuracy | mAPᵛᵃᴵ | F1 Score | Recall |
|---|---|---|---|---|
| Vbai-2.5f | 95.48% | 98.78% | 95.49% | 95.48% |
| Vbai-2.5q | 97.14% | 99.65% | 97.15% | 97.14% |
| Vbai-2.5T+ | 95.24% | 99.12% | 95.26% | 95.24% |
1import torch
2import torch.nn as nn
3import torchvision.transforms as transforms
4from PIL import Image
5import matplotlib.pyplot as plt
6import numpy as np
7import seaborn as sns
8import cv2
9import os
10import torch.nn.functional as F
11from sklearn.metrics import classification_report, confusion_matrix
12
13DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14MODEL_PATH = 'Vbai-2.5/model/path'
15MODEL_TYPE = 'f'
16
17DEMENTIA_DIR = 'dementia/data/dir'
18TUMOR_DIR = 'tumor/data/dir'
19
20TEST_IMAGE_PATH = 'single/test/image/file'
21
22DEM_CLASSES = ['AD Alzheimer Diseases', 'AD Mild Demented', 'AD Moderate Demented',
23 'AD Very Mild Demented', 'CN Non Demented', 'PD Parkinson Diseases']
24TUM_CLASSES = ['Glioma Tumor', 'Meningioma Tumor', 'No Tumor', 'Pituitary Tumor']
25
26
27# --- MODEL ARCHITECTURE ---
28class AttentionModule(nn.Module):
29 def __init__(self, in_channels):
30 super(AttentionModule, self).__init__()
31 self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
32 self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
33 self.sigmoid = nn.Sigmoid()
34
35 def forward(self, x):
36 att = self.sigmoid(self.conv2(F.relu(self.conv1(x))))
37 return x * att, att
38
39
40class MultiTaskBrainModel(nn.Module):
41 def __init__(self, num_dem_classes, num_tum_classes, model_type='f'):
42 super(MultiTaskBrainModel, self).__init__()
43 self.model_type = model_type
44
45 if model_type == 'f':
46 self.conv1 = nn.Conv2d(3, 32, 3, padding=1)
47 self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
48 self.conv3 = nn.Conv2d(64, 128, 3, padding=1)
49 final_ch = 128
50 elif model_type == 'q':
51 self.conv1 = nn.Conv2d(3, 64, 3, padding=1)
52 self.bn1 = nn.BatchNorm2d(64)
53 self.conv2 = nn.Conv2d(64, 128, 3, padding=1)
54 self.bn2 = nn.BatchNorm2d(128)
55 self.conv3 = nn.Conv2d(128, 256, 3, padding=1)
56 self.bn3 = nn.BatchNorm2d(256)
57 self.conv4 = nn.Conv2d(256, 512, 3, padding=1)
58 self.bn4 = nn.BatchNorm2d(512)
59 final_ch = 512
60
61 self.pool = nn.MaxPool2d(2, 2)
62 self.relu = nn.ReLU()
63 self.dropout = nn.Dropout(0.5 if model_type == 'q' else 0.3)
64
65 self.edge_conv1 = nn.Conv2d(1, 16, 3, padding=1)
66 self.edge_conv2 = nn.Conv2d(16, 32, 3, padding=1)
67 self.edge_pool = nn.AdaptiveAvgPool2d(28)
68
69 self.dem_att = AttentionModule(final_ch)
70 self.tum_att = AttentionModule(final_ch)
71
72 if model_type == 'q':
73 self.feat_dim = final_ch * 14 * 14
74 self.edge_dim = 32 * 14 * 14
75 self.edge_pool = nn.AdaptiveAvgPool2d(14)
76 else:
77 self.feat_dim = final_ch * 28 * 28
78 self.edge_dim = 32 * 28 * 28
79
80 self.dem_fc = nn.Sequential(
81 nn.Linear(self.feat_dim + self.edge_dim, 512 if model_type == 'f' else 1024),
82 nn.ReLU(),
83 nn.Dropout(0.4),
84 nn.Linear(512 if model_type == 'f' else 1024, num_dem_classes)
85 )
86
87 self.tum_fc = nn.Sequential(
88 nn.Linear(self.feat_dim + self.edge_dim, 512 if model_type == 'f' else 1024),
89 nn.ReLU(),
90 nn.Dropout(0.4),
91 nn.Linear(512 if model_type == 'f' else 1024, num_tum_classes)
92 )
93
94 def forward(self, x, edge_x):
95 if self.model_type == 'f':
96 x = self.pool(self.relu(self.conv1(x)))
97 x = self.pool(self.relu(self.conv2(x)))
98 x = self.relu(self.conv3(x))
99 x = self.pool(x)
100 else:
101 x = self.pool(self.relu(self.bn1(self.conv1(x))))
102 x = self.pool(self.relu(self.bn2(self.conv2(x))))
103 x = self.pool(self.relu(self.bn3(self.conv3(x))))
104 x = self.relu(self.bn4(self.conv4(x)))
105 x = self.pool(x)
106
107 e = self.pool(self.relu(self.edge_conv1(edge_x)))
108 e = self.relu(self.edge_conv2(e))
109 e = self.edge_pool(e)
110 e_flat = e.view(e.size(0), -1)
111
112 d_x, d_att = self.dem_att(x)
113 d_flat = d_x.view(d_x.size(0), -1)
114 dem_out = self.dem_fc(torch.cat([d_flat, e_flat], dim=1))
115
116 t_x, t_att = self.tum_att(x)
117 t_flat = t_x.view(t_x.size(0), -1)
118 tum_out = self.tum_fc(torch.cat([t_flat, e_flat], dim=1))
119
120 return dem_out, tum_out, d_att, t_att
121
122
123transform = transforms.Compose([
124 transforms.Resize((224, 224)),
125 transforms.ToTensor(),
126 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
127])
128
129edge_transform = transforms.Compose([
130 transforms.Resize((224, 224)),
131 transforms.Grayscale(num_output_channels=1),
132 transforms.ToTensor()
133])
134
135
136def analyze_single_image(model, image_path):
137 print(f"\nIs being analyzed: {image_path}")
138 if not os.path.exists(image_path):
139 print("File not found.")
140 return
141
142 try:
143 raw_image = Image.open(image_path).convert('RGB')
144 img_tensor = transform(raw_image).unsqueeze(0).to(DEVICE)
145 edge_tensor = edge_transform(raw_image).unsqueeze(0).to(DEVICE)
146
147 model.eval()
148 with torch.no_grad():
149 d_out, t_out, d_att, t_att = model(img_tensor, edge_tensor)
150
151 d_prob = F.softmax(d_out, dim=1)
152 t_prob = F.softmax(t_out, dim=1)
153
154 d_pred = torch.argmax(d_prob).item()
155 t_pred = torch.argmax(t_prob).item()
156
157 print("-" * 50)
158 print(f"DEMENTIA: {DEM_CLASSES[d_pred]} (%{d_prob[0][d_pred] * 100:.1f})")
159 print(f"TUMOR : {TUM_CLASSES[t_pred]} (%{t_prob[0][t_pred] * 100:.1f})")
160 print("-" * 50)
161
162 d_map = d_att.detach().cpu().numpy()[0, 0]
163 t_map = t_att.detach().cpu().numpy()[0, 0]
164
165 d_map = cv2.resize(d_map, (224, 224))
166 t_map = cv2.resize(t_map, (224, 224))
167
168 plt.figure(figsize=(12, 4))
169
170 plt.subplot(1, 3, 1)
171 plt.imshow(raw_image)
172 plt.title("Original Image")
173 plt.axis('off')
174
175 plt.subplot(1, 3, 2)
176 plt.imshow(raw_image)
177 plt.imshow(d_map, cmap='Blues', alpha=0.5)
178 plt.title(f"Dementia Attention\n{DEM_CLASSES[d_pred]}")
179 plt.axis('off')
180
181 plt.subplot(1, 3, 3)
182 plt.imshow(raw_image)
183 plt.imshow(t_map, cmap='Reds', alpha=0.5)
184 plt.title(f"Tumor Attention\n{TUM_CLASSES[t_pred]}")
185 plt.axis('off')
186
187 plt.tight_layout()
188 plt.show()
189
190 except Exception as e:
191 print(f"Error: {e}")
192 import traceback
193 traceback.print_exc()
194
195
196def evaluate_dataset_performance(model, dementia_dir, tumor_dir):
197 print("\n" + "=" * 60)
198 print("Starting the performance test")
199 print("=" * 60)
200
201 model.eval()
202
203 print(f"\nDementia data set: {dementia_dir}")
204 d_true, d_pred = [], []
205
206 if os.path.exists(dementia_dir):
207 for idx, cls_name in enumerate(DEM_CLASSES):
208 cls_path = os.path.join(dementia_dir, cls_name)
209 if not os.path.exists(cls_path): continue
210
211 files = [f for f in os.listdir(cls_path) if f.lower().endswith(('.jpg', '.png'))][:50]
212
213 for fname in files:
214 try:
215 img = Image.open(os.path.join(cls_path, fname)).convert('RGB')
216 img_t = transform(img).unsqueeze(0).to(DEVICE)
217 edge_t = edge_transform(img).unsqueeze(0).to(DEVICE)
218 with torch.no_grad():
219 out, _, _, _ = model(img_t, edge_t)
220 d_true.append(idx)
221 d_pred.append(torch.argmax(out, 1).item())
222 except:
223 pass
224
225 if d_true:
226 print(classification_report(d_true, d_pred, target_names=DEM_CLASSES, digits=3))
227
228 print(f"\nTumor dataset: {tumor_dir}")
229 t_true, t_pred = [], []
230
231 if os.path.exists(tumor_dir):
232 for idx, cls_name in enumerate(TUM_CLASSES):
233 cls_path = os.path.join(tumor_dir, cls_name)
234 if not os.path.exists(cls_path): continue
235
236 files = [f for f in os.listdir(cls_path) if f.lower().endswith(('.jpg', '.png'))][:50]
237
238 for fname in files:
239 try:
240 img = Image.open(os.path.join(cls_path, fname)).convert('RGB')
241 img_t = transform(img).unsqueeze(0).to(DEVICE)
242 edge_t = edge_transform(img).unsqueeze(0).to(DEVICE)
243 with torch.no_grad():
244 _, out, _, _ = model(img_t, edge_t)
245 t_true.append(idx)
246 t_pred.append(torch.argmax(out, 1).item())
247 except:
248 pass
249
250 if t_true:
251 print(classification_report(t_true, t_pred, target_names=TUM_CLASSES, digits=3))
252
253
254def main():
255 print("System loading...")
256 model = MultiTaskBrainModel(len(DEM_CLASSES), len(TUM_CLASSES), model_type=MODEL_TYPE).to(DEVICE)
257
258 try:
259 model.load_state_dict(torch.load(MODEL_PATH, map_location=DEVICE))
260 print(f"Model is ready: {MODEL_PATH}")
261 except Exception as e:
262 print(f"Model loading error: {e}")
263 return
264
265 print("\nOPTIONS:")
266 print("1. Analyze the single image")
267 print("2. Analyze the all data set")
268
269 secim = input("Your choice (1 or 2): ")
270
271 if secim == '1':
272 analyze_single_image(model, TEST_IMAGE_PATH)
273 elif secim == '2':
274 evaluate_dataset_performance(model, DEMENTIA_DIR, TUMOR_DIR)
275 else:
276 print("Invalid choose.")
277
278
279if __name__ == '__main__':
280 main()1import torch
2import torch.nn as nn
3import torchvision.transforms as transforms
4from PIL import Image
5import matplotlib.pyplot as plt
6import numpy as np
7import seaborn as sns
8import cv2
9import os
10import torch.nn.functional as F
11from sklearn.metrics import classification_report, confusion_matrix
12
13DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14MODEL_PATH = 'Vbai-2.5+/model/path'
15
16DEMENTIA_DIR = 'dementia/data/dir'
17TUMOR_DIR = 'tumor/data/dir'
18
19TEST_IMAGE_PATH = 'single/test/image/file'
20
21DEM_CLASSES = ['AD Alzheimer Diseases', 'AD Mild Demented', 'AD Moderate Demented',
22 'AD Very Mild Demented', 'CN Non Demented', 'PD Parkinson Diseases']
23TUM_CLASSES = ['Glioma Tumor', 'Meningioma Tumor', 'No Tumor', 'Pituitary Tumor']
24
25
26# --- MODEL ARCHITECTURE (Vbai-2.5+ / Only Q variant / No Edge Branch) ---
27class AttentionModule(nn.Module):
28 def __init__(self, in_channels):
29 super(AttentionModule, self).__init__()
30 self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
31 self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
32 self.sigmoid = nn.Sigmoid()
33
34 def forward(self, x):
35 att = self.sigmoid(self.conv2(F.relu(self.conv1(x))))
36 return x * att, att
37
38
39class MultiTaskBrainModelPlus(nn.Module):
40 def __init__(self):
41 super(MultiTaskBrainModelPlus, self).__init__()
42
43 # Shared Backbone (Q variant only)
44 self.conv1 = nn.Conv2d(3, 64, 3, padding=1)
45 self.bn1 = nn.BatchNorm2d(64)
46 self.conv2 = nn.Conv2d(64, 128, 3, padding=1)
47 self.bn2 = nn.BatchNorm2d(128)
48 self.conv3 = nn.Conv2d(128, 256, 3, padding=1)
49 self.bn3 = nn.BatchNorm2d(256)
50 self.conv4 = nn.Conv2d(256, 512, 3, padding=1)
51 self.bn4 = nn.BatchNorm2d(512)
52
53 self.pool = nn.MaxPool2d(2, 2)
54 self.relu = nn.ReLU()
55 self.dropout = nn.Dropout(0.5)
56
57 final_ch = 512
58 self.feat_dim = final_ch * 14 * 14
59
60 # Dementia Head (6 classes)
61 self.dem_att = AttentionModule(final_ch)
62 self.dem_fc = nn.Sequential(
63 nn.Linear(self.feat_dim, 1024),
64 nn.ReLU(),
65 nn.Dropout(0.4),
66 nn.Linear(1024, 256),
67 nn.ReLU(),
68 nn.Dropout(0.3),
69 nn.Linear(256, 6)
70 )
71
72 # Tumor Head (4 classes)
73 self.tum_att = AttentionModule(final_ch)
74 self.tum_fc = nn.Sequential(
75 nn.Linear(self.feat_dim, 1024),
76 nn.ReLU(),
77 nn.Dropout(0.4),
78 nn.Linear(1024, 256),
79 nn.ReLU(),
80 nn.Dropout(0.3),
81 nn.Linear(256, 4)
82 )
83
84 def forward(self, x):
85 # Backbone
86 x = self.pool(self.relu(self.bn1(self.conv1(x))))
87 x = self.pool(self.relu(self.bn2(self.conv2(x))))
88 x = self.pool(self.relu(self.bn3(self.conv3(x))))
89 x = self.relu(self.bn4(self.conv4(x)))
90 x = self.pool(x) # 14x14
91
92 # Dementia path
93 d_x, d_att = self.dem_att(x)
94 d_flat = d_x.view(d_x.size(0), -1)
95 dem_out = self.dem_fc(d_flat)
96
97 # Tumor path
98 t_x, t_att = self.tum_att(x)
99 t_flat = t_x.view(t_x.size(0), -1)
100 tum_out = self.tum_fc(t_flat)
101
102 return dem_out, tum_out, d_att, t_att
103
104
105transform = transforms.Compose([
106 transforms.Resize((224, 224)),
107 transforms.ToTensor(),
108 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
109])
110
111
112def analyze_single_image(model, image_path):
113 print(f"\nIs being analyzed: {image_path}")
114 if not os.path.exists(image_path):
115 print("File not found.")
116 return
117
118 try:
119 raw_image = Image.open(image_path).convert('RGB')
120 img_tensor = transform(raw_image).unsqueeze(0).to(DEVICE)
121
122 model.eval()
123 with torch.no_grad():
124 d_out, t_out, d_att, t_att = model(img_tensor)
125
126 d_prob = F.softmax(d_out, dim=1)
127 t_prob = F.softmax(t_out, dim=1)
128
129 d_pred = torch.argmax(d_prob).item()
130 t_pred = torch.argmax(t_prob).item()
131
132 print("-" * 50)
133 print(f"DEMENTIA: {DEM_CLASSES[d_pred]} (%{d_prob[0][d_pred] * 100:.1f})")
134 print(f"TUMOR : {TUM_CLASSES[t_pred]} (%{t_prob[0][t_pred] * 100:.1f})")
135 print("-" * 50)
136
137 d_map = d_att.detach().cpu().numpy()[0, 0]
138 t_map = t_att.detach().cpu().numpy()[0, 0]
139
140 d_map = cv2.resize(d_map, (224, 224))
141 t_map = cv2.resize(t_map, (224, 224))
142
143 plt.figure(figsize=(12, 4))
144
145 plt.subplot(1, 3, 1)
146 plt.imshow(raw_image)
147 plt.title("Original Image")
148 plt.axis('off')
149
150 plt.subplot(1, 3, 2)
151 plt.imshow(raw_image)
152 plt.imshow(d_map, cmap='Blues', alpha=0.5)
153 plt.title(f"Dementia Attention\n{DEM_CLASSES[d_pred]}")
154 plt.axis('off')
155
156 plt.subplot(1, 3, 3)
157 plt.imshow(raw_image)
158 plt.imshow(t_map, cmap='Reds', alpha=0.5)
159 plt.title(f"Tumor Attention\n{TUM_CLASSES[t_pred]}")
160 plt.axis('off')
161
162 plt.tight_layout()
163 plt.show()
164
165 except Exception as e:
166 print(f"Error: {e}")
167 import traceback
168 traceback.print_exc()
169
170
171def evaluate_dataset_performance(model, dementia_dir, tumor_dir):
172 print("\n" + "=" * 60)
173 print("Starting the performance test")
174 print("=" * 60)
175
176 model.eval()
177
178 print(f"\nDementia data set: {dementia_dir}")
179 d_true, d_pred = [], []
180
181 if os.path.exists(dementia_dir):
182 for idx, cls_name in enumerate(DEM_CLASSES):
183 cls_path = os.path.join(dementia_dir, cls_name)
184 if not os.path.exists(cls_path): continue
185
186 files = [f for f in os.listdir(cls_path) if f.lower().endswith(('.jpg', '.png'))][:50]
187
188 for fname in files:
189 try:
190 img = Image.open(os.path.join(cls_path, fname)).convert('RGB')
191 img_t = transform(img).unsqueeze(0).to(DEVICE)
192 with torch.no_grad():
193 out, _, _, _ = model(img_t)
194 d_true.append(idx)
195 d_pred.append(torch.argmax(out, 1).item())
196 except:
197 pass
198
199 if d_true:
200 print(classification_report(d_true, d_pred, target_names=DEM_CLASSES, digits=3))
201
202 print(f"\nTumor dataset: {tumor_dir}")
203 t_true, t_pred = [], []
204
205 if os.path.exists(tumor_dir):
206 for idx, cls_name in enumerate(TUM_CLASSES):
207 cls_path = os.path.join(tumor_dir, cls_name)
208 if not os.path.exists(cls_path): continue
209
210 files = [f for f in os.listdir(cls_path) if f.lower().endswith(('.jpg', '.png'))][:50]
211
212 for fname in files:
213 try:
214 img = Image.open(os.path.join(cls_path, fname)).convert('RGB')
215 img_t = transform(img).unsqueeze(0).to(DEVICE)
216 with torch.no_grad():
217 _, out, _, _ = model(img_t)
218 t_true.append(idx)
219 t_pred.append(torch.argmax(out, 1).item())
220 except:
221 pass
222
223 if t_true:
224 print(classification_report(t_true, t_pred, target_names=TUM_CLASSES, digits=3))
225
226
227def main():
228 print("Vbai-2.5+ Test System Loading...")
229 model = MultiTaskBrainModelPlus().to(DEVICE)
230
231 try:
232 model.load_state_dict(torch.load(MODEL_PATH, map_location=DEVICE))
233 print(f"Model is ready: {MODEL_PATH}")
234 except Exception as e:
235 print(f"Model loading error: {e}")
236 return
237
238 print("\nOPTIONS:")
239 print("1. Analyze the single image")
240 print("2. Analyze the all data set")
241
242 secim = input("Your choice (1 or 2): ")
243
244 if secim == '1':
245 analyze_single_image(model, TEST_IMAGE_PATH)
246 elif secim == '2':
247 evaluate_dataset_performance(model, DEMENTIA_DIR, TUMOR_DIR)
248 else:
249 print("Invalid choose.")
250
251
252if __name__ == '__main__':
253 main()