JKL0909 commited on
Commit
69620d2
·
1 Parent(s): f729bb7

commit first

Browse files
Code.ipynb ADDED
@@ -0,0 +1,551 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "44173db3",
7
+ "metadata": {},
8
+ "outputs": [
9
+ {
10
+ "name": "stdout",
11
+ "output_type": "stream",
12
+ "text": [
13
+ "Model 1 test trên train Kaggle2:\n",
14
+ "Accuracy: 0.9222, Precision: 0.9202, Recall: 0.9245, F1: 0.9224\n",
15
+ "Model 2 test trên train Kaggle1:\n",
16
+ "Accuracy: 0.9164, Precision: 0.9220, Recall: 0.9098, F1: 0.9159\n"
17
+ ]
18
+ }
19
+ ],
20
+ "source": [
21
+ "import torch\n",
22
+ "import torch.nn as nn\n",
23
+ "from torchvision import datasets, transforms, models\n",
24
+ "from torch.utils.data import DataLoader\n",
25
+ "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n",
26
+ "import numpy as np\n",
27
+ "\n",
28
+ "DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
29
+ "BATCH_SIZE = 32\n",
30
+ "NUM_CLASSES = 2\n",
31
+ "\n",
32
+ "def get_loader(data_root):\n",
33
+ " transform = transforms.Compose([\n",
34
+ " transforms.Resize((224, 224)),\n",
35
+ " transforms.ToTensor(),\n",
36
+ " ])\n",
37
+ " dataset = datasets.ImageFolder(data_root, transform=transform)\n",
38
+ " loader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=False, num_workers=4)\n",
39
+ " return loader\n",
40
+ "\n",
41
+ "def load_model(weight_path):\n",
42
+ " model = models.efficientnet_b0(weights=None)\n",
43
+ " model.classifier[1] = nn.Linear(model.classifier[1].in_features, NUM_CLASSES)\n",
44
+ " model.load_state_dict(torch.load(weight_path, map_location=DEVICE))\n",
45
+ " model = model.to(DEVICE)\n",
46
+ " model.eval()\n",
47
+ " return model\n",
48
+ "\n",
49
+ "def evaluate(model, loader):\n",
50
+ " all_labels = []\n",
51
+ " all_preds = []\n",
52
+ " with torch.no_grad():\n",
53
+ " for imgs, labels in loader:\n",
54
+ " imgs = imgs.to(DEVICE)\n",
55
+ " outputs = model(imgs)\n",
56
+ " preds = torch.argmax(outputs, dim=1).cpu().numpy()\n",
57
+ " all_preds.extend(preds)\n",
58
+ " all_labels.extend(labels.numpy())\n",
59
+ " acc = accuracy_score(all_labels, all_preds)\n",
60
+ " prec = precision_score(all_labels, all_preds, zero_division=0)\n",
61
+ " rec = recall_score(all_labels, all_preds, zero_division=0)\n",
62
+ " f1 = f1_score(all_labels, all_preds, zero_division=0)\n",
63
+ " return acc, prec, rec, f1"
64
+ ]
65
+ },
66
+ {
67
+ "cell_type": "code",
68
+ "execution_count": null,
69
+ "id": "faf9e19b",
70
+ "metadata": {},
71
+ "outputs": [
72
+ {
73
+ "name": "stdout",
74
+ "output_type": "stream",
75
+ "text": [
76
+ "Model 1 test trên train Kaggle2:\n",
77
+ "Accuracy: 0.9300, Precision: 0.9555, Recall: 0.9020, F1: 0.9280\n",
78
+ "Model 2 test trên train Kaggle1:\n",
79
+ "Accuracy: 0.9200, Precision: 0.9430, Recall: 0.8940, F1: 0.9179\n"
80
+ ]
81
+ }
82
+ ],
83
+ "source": [
84
+ "# Đường dẫn model và data\n",
85
+ "model1_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle1.pth'\n",
86
+ "model2_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle2.pth'\n",
87
+ "data1_train = '/home/ubuntu/vnet/TaoST/Data10kKaggle2/test'\n",
88
+ "data2_train = '/home/ubuntu/vnet/TaoST/Data10kKaggle1/test'\n",
89
+ "# Test chéo\n",
90
+ "model1 = load_model(model1_path)\n",
91
+ "model2 = load_model(model2_path)\n",
92
+ "\n",
93
+ "loader1 = get_loader(data1_train)\n",
94
+ "loader2 = get_loader(data2_train)\n",
95
+ "\n",
96
+ "print(\"Model 1 test trên train Kaggle2:\")\n",
97
+ "acc, prec, rec, f1 = evaluate(model1, loader2)\n",
98
+ "print(f\"Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")\n",
99
+ "\n",
100
+ "print(\"Model 2 test trên train Kaggle1:\")\n",
101
+ "acc, prec, rec, f1 = evaluate(model2, loader1)\n",
102
+ "print(f\"Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")"
103
+ ]
104
+ },
105
+ {
106
+ "cell_type": "code",
107
+ "execution_count": 5,
108
+ "id": "3737fe93",
109
+ "metadata": {},
110
+ "outputs": [
111
+ {
112
+ "name": "stdout",
113
+ "output_type": "stream",
114
+ "text": [
115
+ "Model 1 test trên train Kaggle2:\n",
116
+ "Accuracy: 0.9300, Precision: 0.9555, Recall: 0.9020, F1: 0.9280\n",
117
+ "Model 2 test trên train Kaggle1:\n",
118
+ "Accuracy: 0.9200, Precision: 0.9430, Recall: 0.8940, F1: 0.9179\n"
119
+ ]
120
+ }
121
+ ],
122
+ "source": [
123
+ "# Đường dẫn model và data\n",
124
+ "model1_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle1.pth'\n",
125
+ "model2_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle2.pth'\n",
126
+ "data1_train = '/home/ubuntu/vnet/TaoST/Data10kKaggle2/test'\n",
127
+ "data2_train = '/home/ubuntu/vnet/TaoST/Data10kKaggle1/test'\n",
128
+ "# Test chéo\n",
129
+ "model1 = load_model(model1_path)\n",
130
+ "model2 = load_model(model2_path)\n",
131
+ "\n",
132
+ "loader1 = get_loader(data1_train)\n",
133
+ "loader2 = get_loader(data2_train)\n",
134
+ "\n",
135
+ "print(\"Model 1 test trên train Kaggle2:\")\n",
136
+ "acc, prec, rec, f1 = evaluate(model1, loader2)\n",
137
+ "print(f\"Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")\n",
138
+ "\n",
139
+ "print(\"Model 2 test trên train Kaggle1:\")\n",
140
+ "acc, prec, rec, f1 = evaluate(model2, loader1)\n",
141
+ "print(f\"Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")"
142
+ ]
143
+ },
144
+ {
145
+ "cell_type": "code",
146
+ "execution_count": 6,
147
+ "id": "45ff1792",
148
+ "metadata": {},
149
+ "outputs": [
150
+ {
151
+ "name": "stdout",
152
+ "output_type": "stream",
153
+ "text": [
154
+ "Ensemble (Averaging) trên test: Accuracy: 0.9240, Precision: 0.9511, Recall: 0.8940, F1: 0.9216\n"
155
+ ]
156
+ }
157
+ ],
158
+ "source": [
159
+ "def ensemble_average_predict(model1, model2, loader):\n",
160
+ " all_labels = []\n",
161
+ " all_preds = []\n",
162
+ " model1.eval()\n",
163
+ " model2.eval()\n",
164
+ " with torch.no_grad():\n",
165
+ " for imgs, labels in loader:\n",
166
+ " imgs = imgs.to(DEVICE)\n",
167
+ " out1 = torch.softmax(model1(imgs), dim=1)\n",
168
+ " out2 = torch.softmax(model2(imgs), dim=1)\n",
169
+ " avg_out = (out1 + out2) / 2\n",
170
+ " preds = torch.argmax(avg_out, dim=1).cpu().numpy()\n",
171
+ " all_preds.extend(preds)\n",
172
+ " all_labels.extend(labels.numpy())\n",
173
+ " acc = accuracy_score(all_labels, all_preds)\n",
174
+ " prec = precision_score(all_labels, all_preds, zero_division=0)\n",
175
+ " rec = recall_score(all_labels, all_preds, zero_division=0)\n",
176
+ " f1 = f1_score(all_labels, all_preds, zero_division=0)\n",
177
+ " return acc, prec, rec, f1\n",
178
+ "\n",
179
+ "# Đường dẫn model và data test\n",
180
+ "model1_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle1.pth'\n",
181
+ "model2_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle2.pth'\n",
182
+ "data_test = '/home/ubuntu/vnet/TaoST/Data10kKaggle1/test' # hoặc Data10kKaggle2/test\n",
183
+ "\n",
184
+ "model1 = load_model(model1_path)\n",
185
+ "model2 = load_model(model2_path)\n",
186
+ "loader = get_loader(data_test)\n",
187
+ "\n",
188
+ "acc, prec, rec, f1 = ensemble_average_predict(model1, model2, loader)\n",
189
+ "print(f\"Ensemble (Averaging) trên test: Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")"
190
+ ]
191
+ },
192
+ {
193
+ "cell_type": "code",
194
+ "execution_count": 8,
195
+ "id": "a82b49da",
196
+ "metadata": {},
197
+ "outputs": [
198
+ {
199
+ "name": "stdout",
200
+ "output_type": "stream",
201
+ "text": [
202
+ "Epoch 1/5, Loss: 0.0806\n",
203
+ "Epoch 2/5, Loss: 0.0598\n",
204
+ "Epoch 3/5, Loss: 0.0542\n",
205
+ "Epoch 4/5, Loss: 0.0444\n",
206
+ "Epoch 5/5, Loss: 0.0394\n",
207
+ "GAT Ensemble trên test: Accuracy: 0.9210, Precision: 0.9647, Recall: 0.8740, F1: 0.9171\n"
208
+ ]
209
+ }
210
+ ],
211
+ "source": [
212
+ "import torch\n",
213
+ "import torch.nn as nn\n",
214
+ "from torchvision import models, transforms, datasets\n",
215
+ "from torch.utils.data import DataLoader\n",
216
+ "import torch.nn.functional as F\n",
217
+ "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n",
218
+ "\n",
219
+ "DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
220
+ "NUM_CLASSES = 2\n",
221
+ "BATCH_SIZE = 32\n",
222
+ "EPOCHS = 5\n",
223
+ "\n",
224
+ "class SimpleGATLayer(nn.Module):\n",
225
+ " def __init__(self, in_features, out_features):\n",
226
+ " super().__init__()\n",
227
+ " self.fc = nn.Linear(in_features, out_features)\n",
228
+ " self.attn = nn.Parameter(torch.Tensor(1, out_features))\n",
229
+ " nn.init.xavier_uniform_(self.attn.data, gain=1.414)\n",
230
+ "\n",
231
+ " def forward(self, x):\n",
232
+ " h = self.fc(x)\n",
233
+ " attn_score = torch.matmul(h, self.attn.t())\n",
234
+ " attn_score = F.softmax(attn_score, dim=1)\n",
235
+ " h_prime = (attn_score * h).sum(dim=1)\n",
236
+ " return h_prime\n",
237
+ "\n",
238
+ "class GATEnsembleClassifier(nn.Module):\n",
239
+ " def __init__(self, feature_dim, num_classes):\n",
240
+ " super().__init__()\n",
241
+ " self.gat = SimpleGATLayer(feature_dim, feature_dim)\n",
242
+ " self.classifier = nn.Linear(feature_dim, num_classes)\n",
243
+ "\n",
244
+ " def forward(self, x):\n",
245
+ " h = self.gat(x)\n",
246
+ " out = self.classifier(h)\n",
247
+ " return out\n",
248
+ "\n",
249
+ "def get_feature_extractor(weight_path):\n",
250
+ " model = models.efficientnet_b0(weights=None)\n",
251
+ " model.classifier[1] = nn.Linear(model.classifier[1].in_features, 2)\n",
252
+ " model.load_state_dict(torch.load(weight_path, map_location=DEVICE))\n",
253
+ " backbone = nn.Sequential(*(list(model.children())[:-1]))\n",
254
+ " backbone.eval()\n",
255
+ " return backbone.to(DEVICE)\n",
256
+ "\n",
257
+ "def get_loader(data_root, split):\n",
258
+ " transform = transforms.Compose([\n",
259
+ " transforms.Resize((224, 224)),\n",
260
+ " transforms.ToTensor(),\n",
261
+ " ])\n",
262
+ " dataset = datasets.ImageFolder(f\"{data_root}/{split}\", transform=transform)\n",
263
+ " loader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4)\n",
264
+ " return loader\n",
265
+ "\n",
266
+ "# Đường dẫn model và data\n",
267
+ "model1_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle1.pth'\n",
268
+ "model2_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle2.pth'\n",
269
+ "data_root = '/home/ubuntu/vnet/TaoST/Data10kKaggle'\n",
270
+ "\n",
271
+ "# Load feature extractors (freeze)\n",
272
+ "fe1 = get_feature_extractor(model1_path)\n",
273
+ "fe2 = get_feature_extractor(model2_path)\n",
274
+ "for p in fe1.parameters():\n",
275
+ " p.requires_grad = False\n",
276
+ "for p in fe2.parameters():\n",
277
+ " p.requires_grad = False\n",
278
+ "\n",
279
+ "feature_dim = 1280\n",
280
+ "gat_ensemble = GATEnsembleClassifier(feature_dim, NUM_CLASSES).to(DEVICE)\n",
281
+ "\n",
282
+ "optimizer = torch.optim.Adam(gat_ensemble.parameters(), lr=1e-3)\n",
283
+ "criterion = nn.CrossEntropyLoss()\n",
284
+ "\n",
285
+ "train_loader = get_loader(data_root, 'train')\n",
286
+ "val_loader = get_loader(data_root, 'test')\n",
287
+ "\n",
288
+ "# Huấn luyện GAT ensemble\n",
289
+ "for epoch in range(EPOCHS):\n",
290
+ " gat_ensemble.train()\n",
291
+ " running_loss = 0.0\n",
292
+ " for imgs, labels in train_loader:\n",
293
+ " imgs, labels = imgs.to(DEVICE), labels.to(DEVICE)\n",
294
+ " with torch.no_grad():\n",
295
+ " f1 = fe1(imgs).squeeze(-1).squeeze(-1)\n",
296
+ " f2 = fe2(imgs).squeeze(-1).squeeze(-1)\n",
297
+ " features = torch.stack([f1, f2], dim=1)\n",
298
+ " outputs = gat_ensemble(features)\n",
299
+ " loss = criterion(outputs, labels)\n",
300
+ " optimizer.zero_grad()\n",
301
+ " loss.backward()\n",
302
+ " optimizer.step()\n",
303
+ " running_loss += loss.item() * imgs.size(0)\n",
304
+ " print(f\"Epoch {epoch+1}/{EPOCHS}, Loss: {running_loss/len(train_loader.dataset):.4f}\")\n",
305
+ "\n",
306
+ "# Đánh giá trên tập test\n",
307
+ "gat_ensemble.eval()\n",
308
+ "all_labels = []\n",
309
+ "all_preds = []\n",
310
+ "with torch.no_grad():\n",
311
+ " for imgs, labels in val_loader:\n",
312
+ " imgs = imgs.to(DEVICE)\n",
313
+ " f1 = fe1(imgs).squeeze(-1).squeeze(-1)\n",
314
+ " f2 = fe2(imgs).squeeze(-1).squeeze(-1)\n",
315
+ " features = torch.stack([f1, f2], dim=1)\n",
316
+ " outputs = gat_ensemble(features)\n",
317
+ " preds = torch.argmax(outputs, dim=1).cpu().numpy()\n",
318
+ " all_preds.extend(preds)\n",
319
+ " all_labels.extend(labels.numpy())\n",
320
+ "\n",
321
+ "acc = accuracy_score(all_labels, all_preds)\n",
322
+ "prec = precision_score(all_labels, all_preds, zero_division=0)\n",
323
+ "rec = recall_score(all_labels, all_preds, zero_division=0)\n",
324
+ "f1 = f1_score(all_labels, all_preds, zero_division=0)\n",
325
+ "print(f\"GAT Ensemble trên test: Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")\n",
326
+ "\n",
327
+ "# Lưu lại model GAT nếu muốn\n",
328
+ "torch.save(gat_ensemble.state_dict(), '/home/ubuntu/vnet/FL/gat_ensemble_kaggle.pth')"
329
+ ]
330
+ },
331
+ {
332
+ "cell_type": "code",
333
+ "execution_count": 12,
334
+ "id": "70f1fdff",
335
+ "metadata": {},
336
+ "outputs": [],
337
+ "source": [
338
+ "# Khởi tạo feature extractor và biến feature_dim\n",
339
+ "model1_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle1.pth'\n",
340
+ "model2_path = '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle2.pth'\n",
341
+ "def get_feature_extractor(weight_path):\n",
342
+ " model = models.efficientnet_b0(weights=None)\n",
343
+ " model.classifier[1] = nn.Linear(model.classifier[1].in_features, 2)\n",
344
+ " model.load_state_dict(torch.load(weight_path, map_location=DEVICE))\n",
345
+ " backbone = nn.Sequential(*(list(model.children())[:-1]))\n",
346
+ " backbone.eval()\n",
347
+ " return backbone.to(DEVICE)\n",
348
+ "fe1 = get_feature_extractor(model1_path)\n",
349
+ "fe2 = get_feature_extractor(model2_path)\n",
350
+ "feature_dim = 1280"
351
+ ]
352
+ },
353
+ {
354
+ "cell_type": "code",
355
+ "execution_count": 16,
356
+ "id": "24525bd3",
357
+ "metadata": {},
358
+ "outputs": [
359
+ {
360
+ "name": "stdout",
361
+ "output_type": "stream",
362
+ "text": [
363
+ "GAT Ensemble trên train: Accuracy: 0.9210, Precision: 0.9647, Recall: 0.8740, F1: 0.9171\n"
364
+ ]
365
+ }
366
+ ],
367
+ "source": [
368
+ "# Đảm bảo fe1, fe2, feature_dim đã được load như sau:\n",
369
+ "# fe1 = get_feature_extractor(model1_path)\n",
370
+ "# fe2 = get_feature_extractor(model2_path)\n",
371
+ "# feature_dim = 1280\n",
372
+ "\n",
373
+ "gat_ensemble = GATEnsembleClassifier(feature_dim, NUM_CLASSES).to(DEVICE)\n",
374
+ "gat_ensemble.load_state_dict(torch.load('/home/ubuntu/vnet/FL/gat_ensemble_kaggle.pth', map_location=DEVICE))\n",
375
+ "gat_ensemble.eval()\n",
376
+ "\n",
377
+ "train_loader = get_loader('/home/ubuntu/vnet/TaoST/Data10kKaggle', 'test')\n",
378
+ "\n",
379
+ "all_labels = []\n",
380
+ "all_preds = []\n",
381
+ "with torch.no_grad():\n",
382
+ " for imgs, labels in train_loader:\n",
383
+ " imgs = imgs.to(DEVICE)\n",
384
+ " f1 = fe1(imgs).squeeze(-1).squeeze(-1)\n",
385
+ " f2 = fe2(imgs).squeeze(-1).squeeze(-1)\n",
386
+ " features = torch.stack([f1, f2], dim=1)\n",
387
+ " outputs = gat_ensemble(features)\n",
388
+ " preds = torch.argmax(outputs, dim=1).cpu().numpy()\n",
389
+ " all_preds.extend(preds)\n",
390
+ " all_labels.extend(labels.numpy())\n",
391
+ "\n",
392
+ "acc = accuracy_score(all_labels, all_preds)\n",
393
+ "prec = precision_score(all_labels, all_preds, zero_division=0)\n",
394
+ "rec = recall_score(all_labels, all_preds, zero_division=0)\n",
395
+ "f1 = f1_score(all_labels, all_preds, zero_division=0)\n",
396
+ "print(f\"GAT Ensemble trên train: Accuracy: {acc:.4f}, Precision: {prec:.4f}, Recall: {rec:.4f}, F1: {f1:.4f}\")"
397
+ ]
398
+ },
399
+ {
400
+ "cell_type": "code",
401
+ "execution_count": 1,
402
+ "id": "3a5385c4",
403
+ "metadata": {},
404
+ "outputs": [
405
+ {
406
+ "name": "stdout",
407
+ "output_type": "stream",
408
+ "text": [
409
+ "Exported to /home/ubuntu/vnet/FL/gat_ensemble_kaggle.onnx\n"
410
+ ]
411
+ }
412
+ ],
413
+ "source": [
414
+ "import torch\n",
415
+ "import torch.nn as nn\n",
416
+ "\n",
417
+ "# Định nghĩa lại lớp GATEnsembleClassifier và SimpleGATLayer\n",
418
+ "class SimpleGATLayer(nn.Module):\n",
419
+ " def __init__(self, in_features, out_features):\n",
420
+ " super().__init__()\n",
421
+ " self.fc = nn.Linear(in_features, out_features)\n",
422
+ " self.attn = nn.Parameter(torch.Tensor(1, out_features))\n",
423
+ " nn.init.xavier_uniform_(self.attn.data, gain=1.414)\n",
424
+ "\n",
425
+ " def forward(self, x):\n",
426
+ " h = self.fc(x)\n",
427
+ " attn_score = torch.matmul(h, self.attn.t())\n",
428
+ " attn_score = torch.softmax(attn_score, dim=1)\n",
429
+ " h_prime = (attn_score * h).sum(dim=1)\n",
430
+ " return h_prime\n",
431
+ "\n",
432
+ "class GATEnsembleClassifier(nn.Module):\n",
433
+ " def __init__(self, feature_dim, num_classes):\n",
434
+ " super().__init__()\n",
435
+ " self.gat = SimpleGATLayer(feature_dim, feature_dim)\n",
436
+ " self.classifier = nn.Linear(feature_dim, num_classes)\n",
437
+ "\n",
438
+ " def forward(self, x):\n",
439
+ " h = self.gat(x)\n",
440
+ " out = self.classifier(h)\n",
441
+ " return out\n",
442
+ "\n",
443
+ "# Thông số\n",
444
+ "feature_dim = 1280\n",
445
+ "num_classes = 2\n",
446
+ "DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
447
+ "\n",
448
+ "# Khởi tạo và load trọng số\n",
449
+ "model = GATEnsembleClassifier(feature_dim, num_classes).to(DEVICE)\n",
450
+ "model.load_state_dict(torch.load('/home/ubuntu/vnet/FL/gat_ensemble_kaggle.pth', map_location=DEVICE))\n",
451
+ "model.eval()\n",
452
+ "\n",
453
+ "# Dummy input: batch_size=1, num_models=2, feature_dim=1280\n",
454
+ "dummy_input = torch.randn(1, 2, feature_dim).to(DEVICE)\n",
455
+ "\n",
456
+ "# Export sang ONNX\n",
457
+ "torch.onnx.export(\n",
458
+ " model,\n",
459
+ " dummy_input,\n",
460
+ " \"/home/ubuntu/vnet/FL/gat_ensemble_kaggle.onnx\",\n",
461
+ " input_names=[\"features\"],\n",
462
+ " output_names=[\"output\"],\n",
463
+ " dynamic_axes={\"features\": {0: \"batch_size\"}},\n",
464
+ " opset_version=12\n",
465
+ ")\n",
466
+ "\n",
467
+ "print(\"Exported to /home/ubuntu/vnet/FL/gat_ensemble_kaggle.onnx\")"
468
+ ]
469
+ },
470
+ {
471
+ "cell_type": "code",
472
+ "execution_count": 1,
473
+ "id": "2475f009",
474
+ "metadata": {},
475
+ "outputs": [
476
+ {
477
+ "ename": "ModuleNotFoundError",
478
+ "evalue": "No module named 'onnxruntime'",
479
+ "output_type": "error",
480
+ "traceback": [
481
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
482
+ "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
483
+ "Cell \u001b[0;32mIn[1], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01monnxruntime\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mort\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtorchvision\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m transforms\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mPIL\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Image\n",
484
+ "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'onnxruntime'"
485
+ ]
486
+ }
487
+ ],
488
+ "source": [
489
+ "import onnxruntime as ort\n",
490
+ "from torchvision import transforms\n",
491
+ "from PIL import Image\n",
492
+ "import numpy as np\n",
493
+ "import torch\n",
494
+ "import os\n",
495
+ "\n",
496
+ "# Đường dẫn ONNX model\n",
497
+ "onnx_path = \"/home/ubuntu/vnet/FL/gat_ensemble_kaggle.onnx\"\n",
498
+ "session = ort.InferenceSession(onnx_path, providers=['CPUExecutionProvider'])\n",
499
+ "\n",
500
+ "# Chuẩn bị transform giống như khi train\n",
501
+ "transform = transforms.Compose([\n",
502
+ " transforms.Resize((224, 224)),\n",
503
+ " transforms.ToTensor(),\n",
504
+ "])\n",
505
+ "\n",
506
+ "# Lấy batch ảnh từ folder benign\n",
507
+ "folder = \"/home/ubuntu/vnet/TaoST/Data10kKaggle1/test/benign\"\n",
508
+ "image_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(('.jpg', '.png', '.jpeg'))]\n",
509
+ "batch_size = min(4, len(image_files)) # ví dụ lấy 4 ảnh\n",
510
+ "images = []\n",
511
+ "for img_path in image_files[:batch_size]:\n",
512
+ " img = Image.open(img_path).convert('RGB')\n",
513
+ " img = transform(img)\n",
514
+ " images.append(img)\n",
515
+ "batch_tensor = torch.stack(images) # [batch, 3, 224, 224]\n",
516
+ "\n",
517
+ "# Giả lập feature extractor (thực tế bạn cần xuất features từ fe1, fe2)\n",
518
+ "# Ở đây tạo dummy features để test ONNX\n",
519
+ "feature_dim = 1280\n",
520
+ "num_models = 2\n",
521
+ "features = torch.randn(batch_size, num_models, feature_dim).numpy().astype(np.float32)\n",
522
+ "\n",
523
+ "# Chạy inference với ONNX\n",
524
+ "outputs = session.run([\"output\"], {\"features\": features})\n",
525
+ "print(\"ONNX output shape:\", outputs[0].shape)\n",
526
+ "print(\"ONNX output:\", outputs[0])"
527
+ ]
528
+ }
529
+ ],
530
+ "metadata": {
531
+ "kernelspec": {
532
+ "display_name": "Python 3",
533
+ "language": "python",
534
+ "name": "python3"
535
+ },
536
+ "language_info": {
537
+ "codemirror_mode": {
538
+ "name": "ipython",
539
+ "version": 3
540
+ },
541
+ "file_extension": ".py",
542
+ "mimetype": "text/x-python",
543
+ "name": "python",
544
+ "nbconvert_exporter": "python",
545
+ "pygments_lexer": "ipython3",
546
+ "version": "3.9.21"
547
+ }
548
+ },
549
+ "nbformat": 4,
550
+ "nbformat_minor": 5
551
+ }
Train2model.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.optim as optim
5
+ from torchvision import datasets, transforms, models
6
+ from torch.utils.data import DataLoader
7
+ from torch.multiprocessing import Process, set_start_method
8
+
9
+ try:
10
+ set_start_method('spawn')
11
+ except RuntimeError:
12
+ pass
13
+
14
+ # Cấu hình
15
+ BATCH_SIZE = 32
16
+ EPOCHS = 10
17
+ NUM_CLASSES = 2
18
+ DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
19
+ DATA_ROOTS = [
20
+ '/home/ubuntu/vnet/TaoST/Data10kKaggle1',
21
+ '/home/ubuntu/vnet/TaoST/Data10kKaggle2'
22
+ ]
23
+ MODEL_PATHS = [
24
+ '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle1.pth',
25
+ '/home/ubuntu/vnet/FL/efficientnet_b0_kaggle2.pth'
26
+ ]
27
+
28
+ def get_loaders(data_root):
29
+ train_transform = transforms.Compose([
30
+ transforms.Resize((224, 224)),
31
+ transforms.RandomHorizontalFlip(),
32
+ transforms.ToTensor(),
33
+ ])
34
+ test_transform = transforms.Compose([
35
+ transforms.Resize((224, 224)),
36
+ transforms.ToTensor(),
37
+ ])
38
+ train_set = datasets.ImageFolder(os.path.join(data_root, 'train'), transform=train_transform)
39
+ test_set = datasets.ImageFolder(os.path.join(data_root, 'test'), transform=test_transform)
40
+ train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=4)
41
+ test_loader = DataLoader(test_set, batch_size=BATCH_SIZE, shuffle=False, num_workers=4)
42
+ return train_loader, test_loader
43
+
44
+ def train_model(data_root, model_path):
45
+ train_loader, test_loader = get_loaders(data_root)
46
+ model = models.efficientnet_b0(weights='IMAGENET1K_V1')
47
+ model.classifier[1] = nn.Linear(model.classifier[1].in_features, NUM_CLASSES)
48
+ model = model.to(DEVICE)
49
+ criterion = nn.CrossEntropyLoss()
50
+ optimizer = optim.Adam(model.parameters(), lr=1e-4)
51
+
52
+ for epoch in range(EPOCHS):
53
+ model.train()
54
+ running_loss = 0.0
55
+ for imgs, labels in train_loader:
56
+ imgs, labels = imgs.to(DEVICE), labels.to(DEVICE)
57
+ optimizer.zero_grad()
58
+ outputs = model(imgs)
59
+ loss = criterion(outputs, labels)
60
+ loss.backward()
61
+ optimizer.step()
62
+ running_loss += loss.item() * imgs.size(0)
63
+ print(f"[{data_root}] Epoch {epoch+1}/{EPOCHS}, Loss: {running_loss/len(train_loader.dataset):.4f}")
64
+
65
+ torch.save(model.state_dict(), model_path)
66
+ print(f"Saved model to {model_path}")
67
+
68
+ def main():
69
+ p1 = Process(target=train_model, args=(DATA_ROOTS[0], MODEL_PATHS[0]))
70
+ p2 = Process(target=train_model, args=(DATA_ROOTS[1], MODEL_PATHS[1]))
71
+ p1.start()
72
+ p2.start()
73
+ p1.join()
74
+ p2.join()
75
+
76
+ if __name__ == "__main__":
77
+ main()
efficientnet_b0_kaggle1.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c85f96969b879dbc52e96bac8ae5b9e2c2b5ff9bf230e97214f0e8f79d82215a
3
+ size 16344546
efficientnet_b0_kaggle2.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8538fba8321534a6c3dafd3f594f33d3611b025123ee7190dec064dd9b55bfcc
3
+ size 16344546
gat_ensemble_kaggle.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d1d6da93371de2c8875007d29946740da612e4d9e3932fb6b7e0879631a8cb39
3
+ size 6570324
gat_ensemble_kaggle.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ac1f9c864b7f7f898d19b230920168d8ec06038b3688594fbe3f33317a882b1
3
+ size 6576632