cycool29 commited on
Commit
643d383
·
1 Parent(s): 92bf372
Files changed (4) hide show
  1. configs.py +61 -38
  2. eval.py +26 -18
  3. train.py +45 -9
  4. tuning.py +1 -1
configs.py CHANGED
@@ -7,16 +7,22 @@ import torch.nn as nn
7
  from torchvision.models import (
8
  squeezenet1_0,
9
  SqueezeNet1_0_Weights,
 
 
 
 
10
  mobilenet_v3_small,
11
  MobileNet_V3_Small_Weights,
12
  )
13
- from torchvision.models import squeezenet1_0
 
 
14
 
15
  # Constants
16
  RANDOM_SEED = 123
17
- BATCH_SIZE = 64
18
- NUM_EPOCHS = 100
19
- LEARNING_RATE = 0.00016633192288673592
20
  STEP_SIZE = 10
21
  GAMMA = 0.9
22
  DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
@@ -28,6 +34,8 @@ EXTERNAL_DATA_DIR = r"data/train/external/Task "
28
  COMBINED_DATA_DIR = r"data/train/combined/Task "
29
  TEMP_DATA_DIR = "data/temp/"
30
  NUM_CLASSES = 7
 
 
31
  EARLY_STOPPING_PATIENCE = 20
32
  CLASSES = [
33
  "Alzheimer Disease",
@@ -42,7 +50,7 @@ MODEL_SAVE_PATH = r"output/checkpoints/model.pth"
42
 
43
 
44
  class SqueezeNet1_0WithDropout(nn.Module):
45
- def __init__(self, num_classes=1000):
46
  super(SqueezeNet1_0WithDropout, self).__init__()
47
  squeezenet = squeezenet1_0(weights=SqueezeNet1_0_Weights.DEFAULT)
48
  self.features = squeezenet.features
@@ -52,79 +60,94 @@ class SqueezeNet1_0WithDropout(nn.Module):
52
  nn.ReLU(inplace=True),
53
  nn.AdaptiveAvgPool2d((1, 1)),
54
  )
 
 
 
55
 
56
  def forward(self, x):
57
  x = self.features(x)
58
  x = self.classifier(x)
 
59
  x = torch.flatten(x, 1)
60
  return x
61
 
62
 
63
- # class ShuffleNetV2WithDropout(nn.Module):
64
- # def __init__(self, num_classes=1000):
65
- # super(ShuffleNetV2WithDropout, self).__init__()
66
- # shufflenet = shufflenet_v2_x2_0(weights=ShuffleNet_V2_X2_0_Weights)
67
- # self.features = shufflenet.features
68
- # self.classifier = nn.Sequential(
69
- # nn.Conv2d(1024, num_classes, kernel_size=1),
70
- # nn.BatchNorm2d(num_classes), # add batch normalization
71
- # nn.ReLU(inplace=True),
72
- # nn.AdaptiveAvgPool2d((1, 1))
73
- # )
 
 
 
74
 
75
- # def forward(self, x):
76
- # x = self.features(x)
77
- # x = self.classifier(x)
78
- # x = torch.flatten(x, 1)
79
- # return x
 
80
 
81
 
82
- class MobileNetV3SmallWithDropout(nn.Module):
83
- def __init__(self, num_classes=1000):
84
- super(MobileNetV3SmallWithDropout, self).__init__()
85
- mobilenet = mobilenet_v3_small(weights=MobileNet_V3_Small_Weights)
86
- self.features = mobilenet.features
87
  self.classifier = nn.Sequential(
88
- nn.Conv2d(576, num_classes, kernel_size=1),
89
  nn.BatchNorm2d(num_classes), # add batch normalization
90
  nn.ReLU(inplace=True),
91
  nn.AdaptiveAvgPool2d((1, 1)),
92
  )
 
 
 
93
 
94
  def forward(self, x):
95
  x = self.features(x)
96
  x = self.classifier(x)
 
97
  x = torch.flatten(x, 1)
98
  return x
99
 
100
 
101
- class ResNet18WithNorm(nn.Module):
102
- def __init__(self, num_classes=1000):
103
- super(ResNet18WithNorm, self).__init__()
104
- resnet = resnet18(pretrained=False)
105
- self.features = nn.Sequential(
106
- *list(resnet.children())[:-2]
107
- ) # Remove last 2 layers (avgpool and fc)
108
  self.classifier = nn.Sequential(
 
 
 
109
  nn.AdaptiveAvgPool2d((1, 1)),
110
- nn.Flatten(),
111
- nn.Linear(512, num_classes),
112
- nn.BatchNorm1d(num_classes), # Add batch normalization
113
  )
 
 
 
114
 
115
  def forward(self, x):
116
  x = self.features(x)
117
  x = self.classifier(x)
 
118
  x = torch.flatten(x, 1)
119
  return x
120
 
121
 
122
  MODEL = SqueezeNet1_0WithDropout(num_classes=7)
 
123
  print(CLASSES)
124
 
125
  preprocess = transforms.Compose(
126
  [
127
- transforms.Resize((112, 112)), # Resize to 112x112
128
  transforms.ToTensor(), # Convert to tensor
129
  transforms.Grayscale(num_output_channels=3), # Convert to 3 channels
130
  # Normalize 3 channels
 
7
  from torchvision.models import (
8
  squeezenet1_0,
9
  SqueezeNet1_0_Weights,
10
+ squeezenet1_1,
11
+ SqueezeNet1_1_Weights,
12
+ shufflenet_v2_x2_0,
13
+ ShuffleNet_V2_X2_0_Weights,
14
  mobilenet_v3_small,
15
  MobileNet_V3_Small_Weights,
16
  )
17
+
18
+ import torch.nn.functional as F
19
+ from pytorchcv.model_provider import get_model as ptcv_get_model
20
 
21
  # Constants
22
  RANDOM_SEED = 123
23
+ BATCH_SIZE = 16
24
+ NUM_EPOCHS = 40
25
+ LEARNING_RATE = 0.00016662575248025378
26
  STEP_SIZE = 10
27
  GAMMA = 0.9
28
  DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
 
34
  COMBINED_DATA_DIR = r"data/train/combined/Task "
35
  TEMP_DATA_DIR = "data/temp/"
36
  NUM_CLASSES = 7
37
+ LABEL_SMOOTHING_EPSILON = 0.1
38
+ MIXUP_ALPHA = 0.2
39
  EARLY_STOPPING_PATIENCE = 20
40
  CLASSES = [
41
  "Alzheimer Disease",
 
50
 
51
 
52
  class SqueezeNet1_0WithDropout(nn.Module):
53
+ def __init__(self, num_classes, dropout_prob=0.5):
54
  super(SqueezeNet1_0WithDropout, self).__init__()
55
  squeezenet = squeezenet1_0(weights=SqueezeNet1_0_Weights.DEFAULT)
56
  self.features = squeezenet.features
 
60
  nn.ReLU(inplace=True),
61
  nn.AdaptiveAvgPool2d((1, 1)),
62
  )
63
+ self.dropout = nn.Dropout(
64
+ dropout_prob
65
+ ) # Add dropout layer with the specified probability
66
 
67
  def forward(self, x):
68
  x = self.features(x)
69
  x = self.classifier(x)
70
+ x = F.dropout(x, training=self.training) # Apply dropout during training
71
  x = torch.flatten(x, 1)
72
  return x
73
 
74
 
75
+ class SqueezeNet1_1WithDropout(nn.Module):
76
+ def __init__(self, num_classes, dropout_prob=0.5):
77
+ super(SqueezeNet1_1WithDropout, self).__init__()
78
+ squeezenet = squeezenet1_1(weights=SqueezeNet1_1_Weights.DEFAULT)
79
+ self.features = squeezenet.features
80
+ self.classifier = nn.Sequential(
81
+ nn.Conv2d(512, num_classes, kernel_size=1),
82
+ nn.BatchNorm2d(num_classes), # add batch normalization
83
+ nn.ReLU(inplace=True),
84
+ nn.AdaptiveAvgPool2d((1, 1)),
85
+ )
86
+ self.dropout = nn.Dropout(
87
+ dropout_prob
88
+ ) # Add dropout layer with the specified probability
89
 
90
+ def forward(self, x):
91
+ x = self.features(x)
92
+ x = self.classifier(x)
93
+ x = F.dropout(x, training=self.training) # Apply dropout during training
94
+ x = torch.flatten(x, 1)
95
+ return x
96
 
97
 
98
+ class ShuffleNetV2WithDropout(nn.Module):
99
+ def __init__(self, num_classes, dropout_prob=0.5):
100
+ super(ShuffleNetV2WithDropout, self).__init__()
101
+ shufflenet = shufflenet_v2_x2_0(weights=ShuffleNet_V2_X2_0_Weights.DEFAULT)
102
+ self.features = shufflenet.features
103
  self.classifier = nn.Sequential(
104
+ nn.Conv2d(1024, num_classes, kernel_size=1),
105
  nn.BatchNorm2d(num_classes), # add batch normalization
106
  nn.ReLU(inplace=True),
107
  nn.AdaptiveAvgPool2d((1, 1)),
108
  )
109
+ self.dropout = nn.Dropout(
110
+ dropout_prob
111
+ ) # Add dropout layer with the specified probability
112
 
113
  def forward(self, x):
114
  x = self.features(x)
115
  x = self.classifier(x)
116
+ x = F.dropout(x, training=self.training) # Apply dropout during training
117
  x = torch.flatten(x, 1)
118
  return x
119
 
120
 
121
+ class MobileNetV3SmallWithDropout(nn.Module):
122
+ def __init__(self, num_classes, dropout_prob=0.5):
123
+ super(MobileNetV3SmallWithDropout, self).__init__()
124
+ mobilenet = mobilenet_v3_small(weights=MobileNet_V3_Small_Weights.DEFAULT)
125
+ self.features = mobilenet.features
 
 
126
  self.classifier = nn.Sequential(
127
+ nn.Conv2d(576, num_classes, kernel_size=1),
128
+ nn.BatchNorm2d(num_classes), # add batch normalization
129
+ nn.ReLU(inplace=True),
130
  nn.AdaptiveAvgPool2d((1, 1)),
 
 
 
131
  )
132
+ self.dropout = nn.Dropout(
133
+ dropout_prob
134
+ ) # Add dropout layer with the specified probability
135
 
136
  def forward(self, x):
137
  x = self.features(x)
138
  x = self.classifier(x)
139
+ x = F.dropout(x, training=self.training) # Apply dropout during training
140
  x = torch.flatten(x, 1)
141
  return x
142
 
143
 
144
  MODEL = SqueezeNet1_0WithDropout(num_classes=7)
145
+ # MODEL = ptcv_get_model("sqnxt23v5_w2", pretrained=False, num_classes=7)
146
  print(CLASSES)
147
 
148
  preprocess = transforms.Compose(
149
  [
150
+ transforms.Resize((274, 274)), # Resize to 112x112
151
  transforms.ToTensor(), # Convert to tensor
152
  transforms.Grayscale(num_output_channels=3), # Convert to 3 channels
153
  # Normalize 3 channels
eval.py CHANGED
@@ -1,30 +1,31 @@
1
  import os
2
  import torch
3
- from torchvision.transforms import transforms
4
  import pathlib
5
  from PIL import Image
6
- from torchmetrics import ConfusionMatrix, Accuracy, F1Score
7
  import matplotlib.pyplot as plt
8
  from sklearn.metrics import (
9
  classification_report,
10
  precision_recall_curve,
 
 
 
 
11
  roc_curve,
12
  auc,
13
- confusion_matrix,
14
  )
 
15
  from configs import *
16
  from data_loader import load_data # Import the load_data function
17
- import numpy as np
18
 
19
  # Constants
20
  DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
21
 
22
  # Load the model
23
  MODEL = MODEL.to(DEVICE)
24
- MODEL.load_state_dict(torch.load(r"C:\Users\User\Documents\Flutter-test\handetect\assets\model.pt", map_location=DEVICE))
25
  MODEL.eval()
26
 
27
-
28
  def predict_image(image_path, model, transform):
29
  model.eval()
30
  correct_predictions = 0
@@ -38,9 +39,6 @@ def predict_image(image_path, model, transform):
38
  predicted_labels = []
39
  predicted_scores = [] # To store predicted class probabilities
40
 
41
- accuracy_metric = Accuracy(num_classes=NUM_CLASSES, task="multiclass")
42
- f1_metric = F1Score(num_classes=NUM_CLASSES, task="multiclass")
43
-
44
  with torch.no_grad():
45
  for image_file in images:
46
  print("---------------------------")
@@ -67,22 +65,20 @@ def predict_image(image_path, model, transform):
67
  correct_predictions += 1
68
 
69
  # Calculate accuracy and f1 score
70
- accuracy = correct_predictions / total_predictions
71
  print("Accuracy:", accuracy)
72
- f1 = f1_metric(torch.tensor(predicted_labels), torch.tensor(true_classes)).item()
73
  print("Weighted F1 Score:", f1)
74
 
75
  # Convert the lists to tensors
76
  predicted_labels_tensor = torch.tensor(predicted_labels)
77
  true_classes_tensor = torch.tensor(true_classes)
78
 
79
- # Create a confusion matrix
80
- conf_matrix = ConfusionMatrix(num_classes=NUM_CLASSES, task="multiclass")
81
- conf_matrix(predicted_labels_tensor, true_classes_tensor)
82
 
83
  # Plot the confusion matrix
84
- conf_matrix.compute()
85
- conf_matrix.plot()
86
  plt.title("Confusion Matrix")
87
  plt.show()
88
 
@@ -92,8 +88,20 @@ def predict_image(image_path, model, transform):
92
  true_classes, predicted_labels, target_names=class_names
93
  )
94
  print("Classification Report:\n", report)
95
-
96
-
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
 
99
  # Call predict_image function with your image path
 
1
  import os
2
  import torch
3
+ import numpy as np
4
  import pathlib
5
  from PIL import Image
 
6
  import matplotlib.pyplot as plt
7
  from sklearn.metrics import (
8
  classification_report,
9
  precision_recall_curve,
10
+ accuracy_score,
11
+ f1_score,
12
+ confusion_matrix,
13
+ ConfusionMatrixDisplay,
14
  roc_curve,
15
  auc,
 
16
  )
17
+ from sklearn.preprocessing import label_binarize
18
  from configs import *
19
  from data_loader import load_data # Import the load_data function
 
20
 
21
  # Constants
22
  DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
23
 
24
  # Load the model
25
  MODEL = MODEL.to(DEVICE)
26
+ MODEL.load_state_dict(torch.load(MODEL_SAVE_PATH, map_location=DEVICE))
27
  MODEL.eval()
28
 
 
29
  def predict_image(image_path, model, transform):
30
  model.eval()
31
  correct_predictions = 0
 
39
  predicted_labels = []
40
  predicted_scores = [] # To store predicted class probabilities
41
 
 
 
 
42
  with torch.no_grad():
43
  for image_file in images:
44
  print("---------------------------")
 
65
  correct_predictions += 1
66
 
67
  # Calculate accuracy and f1 score
68
+ accuracy = accuracy_score(true_classes, predicted_labels)
69
  print("Accuracy:", accuracy)
70
+ f1 = f1_score(true_classes, predicted_labels, average="weighted")
71
  print("Weighted F1 Score:", f1)
72
 
73
  # Convert the lists to tensors
74
  predicted_labels_tensor = torch.tensor(predicted_labels)
75
  true_classes_tensor = torch.tensor(true_classes)
76
 
77
+ # Calculate the confusion matrix
78
+ conf_matrix = confusion_matrix(true_classes, predicted_labels)
 
79
 
80
  # Plot the confusion matrix
81
+ ConfusionMatrixDisplay(confusion_matrix=conf_matrix, display_labels=CLASSES).plot(cmap=plt.cm.Blues)
 
82
  plt.title("Confusion Matrix")
83
  plt.show()
84
 
 
88
  true_classes, predicted_labels, target_names=class_names
89
  )
90
  print("Classification Report:\n", report)
91
+
92
+ # Calculate precision and recall for each class
93
+ true_classes_binary = label_binarize(true_classes, classes=range(NUM_CLASSES))
94
+ precision, recall, _ = precision_recall_curve(
95
+ true_classes_binary.ravel(), np.array(predicted_scores).ravel()
96
+ )
97
+
98
+ # Plot precision-recall curve
99
+ plt.figure(figsize=(10, 6))
100
+ plt.plot(recall, precision)
101
+ plt.title("Precision-Recall Curve")
102
+ plt.xlabel("Recall")
103
+ plt.ylabel("Precision")
104
+ plt.show()
105
 
106
 
107
  # Call predict_image function with your image path
train.py CHANGED
@@ -7,12 +7,44 @@ from models import *
7
  from torch.utils.tensorboard import SummaryWriter
8
  from configs import *
9
  import data_loader
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
 
12
  def setup_tensorboard():
13
  return SummaryWriter(log_dir="output/tensorboard/training")
14
 
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def load_and_preprocess_data():
17
  return data_loader.load_data(
18
  RAW_DATA_DIR + str(TASK),
@@ -26,7 +58,7 @@ def initialize_model_optimizer_scheduler():
26
  model = MODEL.to(DEVICE)
27
  criterion = nn.CrossEntropyLoss()
28
  optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)
29
- scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=STEP_SIZE, gamma=GAMMA)
30
  return model, criterion, optimizer, scheduler
31
 
32
 
@@ -35,7 +67,7 @@ def plot_and_log_metrics(metrics_dict, step, writer, prefix="Train"):
35
  writer.add_scalar(f"{prefix}/{metric_name}", metric_value, step)
36
 
37
 
38
- def train_one_epoch(model, criterion, optimizer, train_loader, epoch):
39
  model.train()
40
  running_loss = 0.0
41
  total_train = 0
@@ -44,11 +76,15 @@ def train_one_epoch(model, criterion, optimizer, train_loader, epoch):
44
  for i, (inputs, labels) in enumerate(train_loader, 0):
45
  inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)
46
  optimizer.zero_grad()
47
- if model.__class__.__name__ == "GoogLeNet":
48
- outputs = model(inputs).logits
49
- else:
50
- outputs = model(inputs)
51
- loss = criterion(outputs, labels)
 
 
 
 
52
  loss.backward()
53
  optimizer.step()
54
  running_loss += loss.item()
@@ -107,7 +143,7 @@ def main_training_loop():
107
  print("Learning rate:", scheduler.get_last_lr()[0])
108
 
109
  avg_train_loss, train_accuracy = train_one_epoch(
110
- model, criterion, optimizer, train_loader, epoch
111
  )
112
  AVG_TRAIN_LOSS_HIST.append(avg_train_loss)
113
  TRAIN_ACC_HIST.append(train_accuracy)
@@ -154,7 +190,7 @@ def main_training_loop():
154
  )
155
  )
156
  break
157
-
158
  # Ensure the parent directory exists
159
  os.makedirs(os.path.dirname(MODEL_SAVE_PATH), exist_ok=True)
160
  torch.save(model.state_dict(), MODEL_SAVE_PATH)
 
7
  from torch.utils.tensorboard import SummaryWriter
8
  from configs import *
9
  import data_loader
10
+ import torch.nn.functional as F
11
+ import numpy as np
12
+
13
+
14
+ class LabelSmoothingLoss(nn.Module):
15
+ def __init__(self, epsilon=0.1, num_classes=2):
16
+ super(LabelSmoothingLoss, self).__init__()
17
+ self.epsilon = epsilon
18
+ self.num_classes = num_classes
19
+
20
+ def forward(self, input, target):
21
+ target_smooth = (1 - self.epsilon) * target + self.epsilon / self.num_classes
22
+ return nn.CrossEntropyLoss()(input, target_smooth)
23
 
24
 
25
  def setup_tensorboard():
26
  return SummaryWriter(log_dir="output/tensorboard/training")
27
 
28
 
29
+ def mixup_data(x, y, alpha=1.0):
30
+ """Returns mixed inputs, pairs of targets, and lambda"""
31
+ if alpha > 0:
32
+ lam = np.random.beta(alpha, alpha)
33
+ else:
34
+ lam = 1
35
+
36
+ batch_size = x.size()[0]
37
+ index = torch.randperm(batch_size)
38
+
39
+ mixed_x = lam * x + (1 - lam) * x[index, :]
40
+ y_a, y_b = y, y[index]
41
+ return mixed_x, y_a, y_b, lam
42
+
43
+
44
+ def mixup_criterion(criterion, pred, y_a, y_b, lam):
45
+ return lam * criterion(pred, y_a) + (1 - lam) * criterion(pred, y_b)
46
+
47
+
48
  def load_and_preprocess_data():
49
  return data_loader.load_data(
50
  RAW_DATA_DIR + str(TASK),
 
58
  model = MODEL.to(DEVICE)
59
  criterion = nn.CrossEntropyLoss()
60
  optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)
61
+ scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=NUM_EPOCHS)
62
  return model, criterion, optimizer, scheduler
63
 
64
 
 
67
  writer.add_scalar(f"{prefix}/{metric_name}", metric_value, step)
68
 
69
 
70
+ def train_one_epoch(model, criterion, optimizer, train_loader, epoch, alpha):
71
  model.train()
72
  running_loss = 0.0
73
  total_train = 0
 
76
  for i, (inputs, labels) in enumerate(train_loader, 0):
77
  inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)
78
  optimizer.zero_grad()
79
+
80
+ # Apply mixup
81
+ inputs, targets_a, targets_b, lam = mixup_data(inputs, labels, alpha)
82
+
83
+ outputs = model(inputs)
84
+
85
+ # Calculate mixup loss
86
+ loss = mixup_criterion(criterion, outputs, targets_a, targets_b, lam)
87
+
88
  loss.backward()
89
  optimizer.step()
90
  running_loss += loss.item()
 
143
  print("Learning rate:", scheduler.get_last_lr()[0])
144
 
145
  avg_train_loss, train_accuracy = train_one_epoch(
146
+ model, criterion, optimizer, train_loader, epoch, MIXUP_ALPHA
147
  )
148
  AVG_TRAIN_LOSS_HIST.append(avg_train_loss)
149
  TRAIN_ACC_HIST.append(train_accuracy)
 
190
  )
191
  )
192
  break
193
+ MODEL_SAVE_PATH = "output/checkpoints/model.pth"
194
  # Ensure the parent directory exists
195
  os.makedirs(os.path.dirname(MODEL_SAVE_PATH), exist_ok=True)
196
  torch.save(model.state_dict(), MODEL_SAVE_PATH)
tuning.py CHANGED
@@ -12,7 +12,7 @@ from torch.utils.tensorboard import SummaryWriter
12
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
13
  EPOCHS = 10
14
  N_TRIALS = 1000
15
- TIMEOUT = 1800
16
 
17
  # Create a TensorBoard writer
18
  writer = SummaryWriter(log_dir="output/tensorboard/tuning")
 
12
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
13
  EPOCHS = 10
14
  N_TRIALS = 1000
15
+ TIMEOUT = 14400
16
 
17
  # Create a TensorBoard writer
18
  writer = SummaryWriter(log_dir="output/tensorboard/tuning")