WMLP Documentation
Overview
A dataset pipeline was developed for the USPS digits 0–6, including loading, and preprocessing. The processed data would be fed into a classification network using a simple MLP with two hidden layers of 100 neurons each and a Leaky ReLU activation. Evaluation was conducted using the balanced accuracy metric, which was implemented from scratch.
WMLP
Implemented a WMLP model, 2 hidden layers; 100 neurons each, with LeakyReLU as the activation function.
Model was trained by optimizing the Cross Entropy Loss as USPS is a multi-class classification task.
Model was evaluated with Balanced Accuracy as a evaluation metric to be robustly evaluate the model across different classes.
Structure
class WMLP(nn.Module):
"""
Multi-Layer Perceptron with 2 hidden layers (100 neurons each).
Args:
input_dim (int): Dimension of input features
output_dim (int): Dimension of output
hidden_dim (int): Number of neurons in each hidden layer (default: 100)
negative_slope (float): Controls the angle of the negative slope for LeakyReLU (default: 0.01)
"""
def __init__(self, input_dim, output_dim, hidden_dim=100, negative_slope=0.01):
super(WMLP, self).__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, hidden_dim)
self.fc3 = nn.Linear(hidden_dim, output_dim)
self.activation = nn.LeakyReLU(negative_slope=negative_slope)
USPS
The dataloader provides image loading and preprocessing for a subset of the USPS collection covering digits 0–6. Data are obtained from official sources, transformed into ready-to-use image/label pairs, partitioned, and saved in the HDF5 file format for convenient access. The loader retrieves one example at a time, ensuring only a single sample is held in memory to minimize resource usage.
Balanced Accuracy
def balanced_accuracy(y_true, y_pred):
"""
Calculate balanced accuracy for multi-class classification.
Balanced accuracy is the average of recall obtained on each class.
It's particularly useful for imbalanced datasets.
Args:
y_true: Ground truth labels (1D array-like)
y_pred: Predicted labels (1D array-like)
Returns:
float: Balanced accuracy score between 0 and 1
Raises:
AssertionError: If inputs are invalid
ValueError: If computation fails
"""
.........
# Calculate recall for each class
recalls = []
for cls in classes:
cls_mask = (y_true == cls)
n_cls = np.sum(cls_mask)
if n_cls == 0:
continue
tp = np.sum((y_true == cls) & (y_pred == cls))
recall = tp / n_cls
recalls.append(recall)
assert len(recalls) > 0, "No valid recalls computed"
return np.mean(recalls)
Misc
Used CookieCutter to make boilerplate project outlet to follow worldwide code conventions
Everything went smoothly (Dennis)
Everything went smoothly (one typo as error)
New knowledge: Sphinx and LUMI
For such a simple project it was fairly easy to run jobs on LUMI. However, I would predict that for a large project with a rapidly changing environment it will be time consuming. (Job-IDs: 13618444, 13631080, 14077470)