diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index d20b1c0..55c29c7 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -6,7 +6,7 @@
-
+
@@ -47,12 +47,15 @@
"Python.experiment-4.executor": "Run",
"Python.experiment-5.executor": "Run",
"Python.experiment-6-convolutional-neural-network.executor": "Run",
+ "Python.experiment-7.executor": "Run",
+ "Python.experiment-8.executor": "Run",
"Python.multilayer-perceptron.executor": "Run",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "master",
- "last_opened_file_path": "/home/arctichawk1/Desktop/Projects/Private/Classification-of-Image-Data-with-MLP-and-CNN"
+ "last_opened_file_path": "/home/arctichawk1/Desktop/Projects/Private/Classification-of-Image-Data-with-MLP-and-CNN",
+ "settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable"
}
}]]>
diff --git a/data/FashionMNIST/raw/t10k-images-idx3-ubyte b/data/FashionMNIST/raw/t10k-images-idx3-ubyte
new file mode 100644
index 0000000..37bac79
Binary files /dev/null and b/data/FashionMNIST/raw/t10k-images-idx3-ubyte differ
diff --git a/data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz b/data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz
new file mode 100644
index 0000000..667844f
Binary files /dev/null and b/data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz differ
diff --git a/data/FashionMNIST/raw/t10k-labels-idx1-ubyte b/data/FashionMNIST/raw/t10k-labels-idx1-ubyte
new file mode 100644
index 0000000..2195a4d
Binary files /dev/null and b/data/FashionMNIST/raw/t10k-labels-idx1-ubyte differ
diff --git a/data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz b/data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz
new file mode 100644
index 0000000..abdddb8
Binary files /dev/null and b/data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz differ
diff --git a/data/FashionMNIST/raw/train-images-idx3-ubyte b/data/FashionMNIST/raw/train-images-idx3-ubyte
new file mode 100644
index 0000000..ff2f5a9
Binary files /dev/null and b/data/FashionMNIST/raw/train-images-idx3-ubyte differ
diff --git a/data/FashionMNIST/raw/train-images-idx3-ubyte.gz b/data/FashionMNIST/raw/train-images-idx3-ubyte.gz
new file mode 100644
index 0000000..e6ee0e3
Binary files /dev/null and b/data/FashionMNIST/raw/train-images-idx3-ubyte.gz differ
diff --git a/data/FashionMNIST/raw/train-labels-idx1-ubyte b/data/FashionMNIST/raw/train-labels-idx1-ubyte
new file mode 100644
index 0000000..30424ca
Binary files /dev/null and b/data/FashionMNIST/raw/train-labels-idx1-ubyte differ
diff --git a/data/FashionMNIST/raw/train-labels-idx1-ubyte.gz b/data/FashionMNIST/raw/train-labels-idx1-ubyte.gz
new file mode 100644
index 0000000..9c4aae2
Binary files /dev/null and b/data/FashionMNIST/raw/train-labels-idx1-ubyte.gz differ
diff --git a/experiment-8.py b/experiment-8.py
index e69de29..c1a6340 100644
--- a/experiment-8.py
+++ b/experiment-8.py
@@ -0,0 +1,134 @@
+import torch
+import torch.nn as nn
+import torch.optim as optim
+from torchvision import datasets, transforms, models
+from torch.utils.data import DataLoader
+import os
+import matplotlib.pyplot as plt
+
+device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
+num_class = 10
+batch_size = 256
+epochs = 10
+lr = 2e-3
+num_workers = os.cpu_count()
+step_size = 5
+gamma = 0.1
+
+transform_train = transforms.Compose([
+ transforms.RandomRotation(20),
+ transforms.RandomHorizontalFlip(),
+ transforms.Grayscale(num_output_channels=3), # MobileNet expects 3 channels
+ transforms.Resize((28, 28)), # Resize the input images to 28x28
+ transforms.ToTensor(),
+])
+
+transform_test = transforms.Compose([
+ transforms.Grayscale(num_output_channels=3),
+ transforms.Resize((28, 28)), # Resize the test images to 28x28
+ transforms.ToTensor(),
+])
+
+train_set = datasets.FashionMNIST(root='.', train=True, download=True, transform=transform_train)
+test_set = datasets.FashionMNIST(root='.', train=False, download=True, transform=transform_test)
+
+train_loader = DataLoader(train_set, batch_size=batch_size, shuffle=True, num_workers=num_workers)
+test_loader = DataLoader(test_set, batch_size=batch_size, shuffle=False, num_workers=num_workers)
+
+model = models.mobilenet_v3_small(weights=models.MobileNet_V3_Small_Weights.IMAGENET1K_V1)
+
+# freezes convolutional layers
+for param in model.features.parameters():
+ param.requires_grad = False
+
+# function to get the size of the features after convolutional layers
+def get_fc_input_size(model, input_size=(3, 28, 28)):
+ batch_size = 16 # uses a small batch size to avoid issues with batch normalization
+ x = torch.randn(batch_size, *input_size).to(device) # Batch size of 16
+ # passes through the model up to the classifier to get the feature map size
+ with torch.no_grad():
+ features = model.features(x)
+ # flattens the feature map to calculate the input size for the first fully connected layer
+ return features.view(batch_size, -1).size(1)
+
+# calculates the correct input size for the first FC layer
+fc_input_size = get_fc_input_size(model, input_size=(3, 28, 28))
+
+# replaces the classifier with new fully connected layers
+model.classifier = nn.Sequential(
+ nn.Linear(fc_input_size, 256),
+ nn.ReLU(),
+ nn.Dropout(0.5),
+ nn.Linear(256, 128),
+ nn.ReLU(),
+ nn.Dropout(0.3),
+ nn.Linear(128, num_class)
+)
+
+# compiles for faster CPU/GPU execution
+model = torch.compile(model)
+model = model.to(device)
+
+criterion = nn.CrossEntropyLoss()
+optimizer = optim.Adam(model.classifier.parameters(), lr=lr)
+scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=step_size, gamma=gamma)
+
+def plot_graph(train_losses, val_accuracies):
+ if not os.path.exists('results'):
+ os.makedirs('results')
+ fig, ax1 = plt.subplots()
+ ax1.set_xlabel('Epochs')
+ ax1.set_ylabel('Training Loss', color='tab:blue')
+ ax1.plot(range(1, len(train_losses)+1), train_losses, color='tab:blue')
+ ax1.tick_params(axis='y', labelcolor='tab:blue')
+ ax2 = ax1.twinx()
+ ax2.set_ylabel('Validation Accuracy', color='tab:orange')
+ ax2.plot(range(1, len(val_accuracies)+1), val_accuracies, color='tab:orange')
+ ax2.tick_params(axis='y', labelcolor='tab:orange')
+ plt.title('Training Loss and Validation Accuracy')
+ fig.savefig('results/experiment-8.png')
+ print("Graph saved to results/experiment-8.png")
+
+def training(model, loader, optimizer, criterion):
+ model.train()
+ running_loss, correct, total = 0.0, 0, 0
+ for images, labels in loader:
+ images, labels = images.to(device), labels.to(device)
+ optimizer.zero_grad(set_to_none=True)
+ with torch.autocast(device_type=device.type, dtype=torch.bfloat16 if device.type=='cpu' else torch.float16):
+ logits = model(images)
+ loss = criterion(logits, labels)
+ loss.backward()
+ optimizer.step()
+ running_loss += loss.item() * images.size(0)
+ preds = logits.argmax(1)
+ correct += (preds == labels).sum().item()
+ total += labels.size(0)
+ return running_loss / total, correct / total
+
+@torch.no_grad()
+def evaluation(model, loader, criterion):
+ model.eval()
+ running_loss, correct, total = 0.0, 0, 0
+ for images, labels in loader:
+ images, labels = images.to(device), labels.to(device)
+ with torch.autocast(device_type=device.type, dtype=torch.bfloat16 if device.type=='cpu' else torch.float16):
+ logits = model(images)
+ loss = criterion(logits, labels)
+ running_loss += loss.item() * images.size(0)
+ preds = logits.argmax(1)
+ correct += (preds == labels).sum().item()
+ total += labels.size(0)
+ return running_loss / total, correct / total
+
+train_losses, val_accuracies = [], []
+
+for epoch in range(1, epochs + 1):
+ train_loss, train_acc = training(model, train_loader, optimizer, criterion)
+ val_loss, val_acc = evaluation(model, test_loader, criterion)
+ train_losses.append(train_loss)
+ val_accuracies.append(val_acc)
+ print(f"Epoch {epoch}, Train Loss: {train_loss:.4f}, Val Loss: {val_loss:.4f}, Val Accuracy: {val_acc:.4f}")
+ scheduler.step()
+
+plot_graph(train_losses, val_accuracies)
\ No newline at end of file
diff --git a/results/experiment-8.png b/results/experiment-8.png
new file mode 100644
index 0000000..c8cc6d7
Binary files /dev/null and b/results/experiment-8.png differ