davidwardan commited on
Commit
56d235c
·
verified ·
1 Parent(s): eeca8e6

Delete src/resnet.py

Browse files
Files changed (1) hide show
  1. src/resnet.py +0 -273
src/resnet.py DELETED
@@ -1,273 +0,0 @@
1
- import torch
2
- from torchvision import models
3
- import torchvision.transforms as transforms
4
- from torchvision.transforms import InterpolationMode
5
- from torch.utils.data import Dataset, DataLoader
6
- import torch.nn as nn
7
- from sklearn.metrics import confusion_matrix
8
- import tqdm
9
- import matplotlib.pyplot as plt
10
- import numpy as np
11
- from src import utils
12
-
13
- plt.style.use("ggplot")
14
- plt.rcParams.update({"font.size": 14})
15
- plt.rcParams.update({"figure.autolayout": True})
16
-
17
-
18
- def main(batch_size=64, epochs=50, classes=("formal", "informal"), train: bool = True):
19
- train_transform = transforms.Compose(
20
- [
21
- transforms.ToPILImage(),
22
- transforms.RandomHorizontalFlip(p=0.5),
23
- transforms.RandomVerticalFlip(p=0.5),
24
- transforms.ColorJitter(
25
- brightness=0.3, contrast=0.3, saturation=0.3, hue=0.1
26
- ),
27
- transforms.RandomRotation(
28
- degrees=30, interpolation=InterpolationMode.BICUBIC
29
- ),
30
- transforms.RandomResizedCrop(
31
- size=224, scale=(0.8, 1.0), interpolation=InterpolationMode.BICUBIC
32
- ),
33
- transforms.ToTensor(),
34
- transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
35
- ]
36
- )
37
-
38
- transform = transforms.Compose(
39
- [
40
- transforms.ToPILImage(),
41
- transforms.Resize([256], interpolation=InterpolationMode.BICUBIC),
42
- transforms.CenterCrop([224]),
43
- transforms.ToTensor(), # Converts the image to [0.0, 1.0] range
44
- transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
45
- ]
46
- )
47
-
48
- # Custom dataset class
49
- class CustomDataset(Dataset):
50
- def __init__(self, data, transform=None):
51
- self.data = data
52
- self.transform = transform
53
-
54
- def __len__(self):
55
- return len(self.data)
56
-
57
- def __getitem__(self, idx):
58
- image, label = self.data[idx]
59
- if self.transform:
60
- image = self.transform(image)
61
- return image, label
62
-
63
- # Load the data
64
- train_data = utils.load_from_pickle("./data/high_res/train.pkl")
65
- val_data = utils.load_from_pickle("./data/high_res/val.pkl")
66
- test_data = utils.load_from_pickle("./data/high_res/test.pkl")
67
-
68
- # process the data to keep only three channels
69
- train_data = [(image[:, :, :3], label) for image, label in train_data]
70
- val_data = [(image[:, :, :3], label) for image, label in val_data]
71
- test_data = [(image[:, :, :3], label) for image, label in test_data]
72
-
73
- # Create custom datasets with transformations
74
- trainset = CustomDataset(train_data, transform=train_transform)
75
- valset = CustomDataset(val_data, transform=transform)
76
- testset = CustomDataset(test_data, transform=transform)
77
-
78
- # Create DataLoaders
79
- trainloader = DataLoader(trainset, batch_size=batch_size, shuffle=True)
80
- valloader = DataLoader(valset, batch_size=batch_size, shuffle=False)
81
- testloader = DataLoader(testset, batch_size=batch_size, shuffle=False)
82
-
83
- # Set the device
84
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
85
- print("Running on {}".format(device))
86
-
87
- # Load a pretrained ResNet model
88
- model = models.resnet50(weights="ResNet50_Weights.IMAGENET1K_V1").to(
89
- device
90
- ) # You can use resnet18, resnet50, etc.
91
-
92
- # Modify the output layer directly to match binary classification
93
- model.fc = nn.Sequential(
94
- nn.Linear(model.fc.in_features, 128),
95
- nn.ReLU(inplace=True),
96
- nn.Linear(128, 1), # 1 output unit for binary classification
97
- ).to(
98
- device
99
- ) # Make sure the head is also on the correct device
100
-
101
- # Print the model architecture
102
- print(model)
103
-
104
- if train:
105
- # Define loss function and optimizer
106
- criterion = nn.BCEWithLogitsLoss() # Binary classification
107
- optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
108
- scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.25)
109
-
110
- # Train the model
111
- optimal_accuracy = 0
112
- patience = 10
113
-
114
- for epoch in tqdm.tqdm(range(epochs)):
115
- model.train()
116
- running_loss = 0.0
117
-
118
- for i, data in enumerate(trainloader, 0):
119
- # Move inputs and labels to the correct device
120
- inputs, labels = data
121
- inputs, labels = (
122
- inputs.to(device),
123
- labels.to(device).float(),
124
- ) # Ensure labels are float for BCEWithLogitsLoss
125
-
126
- # Zero the parameter gradients
127
- optimizer.zero_grad()
128
-
129
- # Forward + backward + optimize
130
- outputs = model(inputs)
131
- loss = criterion(
132
- outputs, labels.unsqueeze(1)
133
- ) # Match output shape (N, 1)
134
- loss.backward()
135
- optimizer.step()
136
-
137
- running_loss += loss.item()
138
- if i % 2000 == 1999:
139
- print(f"[{epoch + 1}, {i + 1}] loss: {running_loss / 2000:.3f}")
140
- running_loss = 0.0
141
-
142
- scheduler.step()
143
-
144
- # Validate the model
145
- model.eval()
146
- correct = 0
147
- total = 0
148
-
149
- with torch.no_grad():
150
- for data in valloader:
151
- images, labels = data
152
- images, labels = images.to(device), labels.to(device).float()
153
- outputs = model(images)
154
- predicted = (
155
- torch.sigmoid(outputs) > 0.5
156
- ).float() # Apply sigmoid and threshold at 0.5
157
- total += labels.size(0)
158
- correct += (predicted == labels.unsqueeze(1)).sum().item()
159
-
160
- accuracy = 100 * correct / total
161
- print(f"Validation accuracy: {accuracy:.2f}%")
162
-
163
- # early stopping
164
- if accuracy > optimal_accuracy:
165
- optimal_accuracy = accuracy
166
- optimal_model = model.state_dict()
167
- patience = 10
168
- else:
169
- patience -= 1
170
-
171
- if patience == 0:
172
- print("Early stopping")
173
- break
174
-
175
- print("Finished Training")
176
-
177
- # Save the model
178
- torch.save(optimal_model, "./weights/ResNet50.pth")
179
- print("Model saved")
180
-
181
- # Load the model and move it to the correct device
182
- model.load_state_dict(
183
- torch.load("./weights/ResNet50.pth", map_location=device, weights_only=True)
184
- )
185
- model.to(device)
186
-
187
- # Test the model
188
- model.eval()
189
- correct = 0
190
- total = 0
191
- y_pred = []
192
- y_true = []
193
-
194
- with torch.no_grad():
195
- for data in tqdm.tqdm(testloader):
196
- images, labels = data
197
- images, labels = images.to(device), labels.to(device).float()
198
- outputs = model(images)
199
- predicted = (
200
- torch.sigmoid(outputs) > 0.5
201
- ).float() # Apply sigmoid and threshold at 0.5
202
-
203
- # store predictions for CM
204
- y_pred.extend(predicted.cpu().numpy())
205
- y_true.extend(labels.cpu().numpy())
206
-
207
- total += labels.size(0)
208
- correct += (predicted == labels.unsqueeze(1)).sum().item()
209
-
210
- accuracy = 100 * correct / total
211
- print(f"Test accuracy: {accuracy:.2f}%")
212
-
213
- print("Finished Testing")
214
-
215
- # Confusion matrix
216
- cm = confusion_matrix(y_true, y_pred, normalize="true")
217
- plt.figure(figsize=(8, 8))
218
- plt.imshow(cm, interpolation="nearest", cmap=plt.cm.Blues)
219
- plt.title("Confusion Matrix")
220
- plt.colorbar()
221
- tick_marks = np.arange(len(classes))
222
- plt.xticks(tick_marks, classes, rotation=45)
223
- plt.yticks(tick_marks, classes)
224
- plt.xlabel("Predicted")
225
- plt.ylabel("True")
226
- plt.savefig("confusion_matrix.pdf", format="pdf")
227
- plt.show()
228
-
229
- # Show test images with predicted label and actual label
230
- def imshow(img, title=None):
231
- """This function plots a tensor"""
232
- img = img / 2 + 0.5 # unnormalize
233
- npimg = img.cpu().numpy() # convert to numpy for display
234
- plt.imshow(np.transpose(npimg, (1, 2, 0))) # reshape to (H, W, C)
235
- if title is not None:
236
- plt.title(title)
237
- plt.show()
238
-
239
- def show_predictions(model, dataloader, device, classes):
240
- """Function to show images with predicted and actual labels."""
241
- model.eval()
242
-
243
- with torch.no_grad():
244
- for i, data in enumerate(dataloader):
245
- images, labels = data
246
- images, labels = images.to(device), labels.to(device).float()
247
-
248
- # Forward pass to get predictions
249
- outputs = model(images)
250
- outputs = outputs.squeeze(dim=1) # Ensure shape is [batch_size]
251
- predicted = (torch.sigmoid(outputs) > 0.5).float()
252
-
253
- # Plot each image with its predicted and actual labels
254
- for j in range(images.size(0)):
255
- imshow(images[j].cpu()) # Unnormalize and plot image
256
-
257
- # Convert predictions and labels to text (formal/informal)
258
- pred_label = classes[int(predicted[j].item())]
259
- actual_label = classes[int(labels[j].item())]
260
-
261
- # Display the predicted and actual labels
262
- print(f"Predicted: {pred_label}, Actual: {actual_label}")
263
-
264
- # Optionally, stop after displaying N images
265
- if i * len(images) + j >= 20: # Show 5 images, adjust as needed
266
- return
267
-
268
- # Call the function to display images along with predictions
269
- # show_predictions(model, testloader, device, classes)
270
-
271
-
272
- if __name__ == "__main__":
273
- main()