This repository contains PyTorch code and experiment artifacts for fine-grained knife image classification. The project trains pretrained convolutional image classifiers, mainly EfficientNet and DenseNet variants from timm, to classify knife images into 192 classes.
The code appears to have been developed and run in Google Colab with the dataset mounted from Google Drive at /content/drive/My Drive/Knives.
| Path | Description |
|---|---|
train.py |
Training entry point. Loads train.csv and val.csv, fine-tunes a pretrained timm model, logs training/validation metrics, saves checkpoints, and writes plots. |
test.py |
Evaluation entry point. Loads test.csv, restores a saved model checkpoint, and reports test mAP. |
data.py |
Custom knifeDataset class for reading image paths from CSV files and applying train/validation/test transforms. |
config.py |
Active hyperparameter configuration: class count, image size, batch size, epochs, and learning rate. |
utils.py |
Logging, metric helpers, average meters, checkpoint helper, and loss utilities. |
requirements.txt |
Pinned Python package versions used by the project. |
train.csv, val.csv, test.csv |
Dataset index files with Id,Label columns. The image files themselves are not included in this repository. |
Knife.ipynb |
Colab notebook used to mount Drive, install dependencies, and run training/testing commands. |
Experiments/ |
Experiment notebook, config snapshots, metric plots, and a training log. |
Paper/ |
Project report files in PDF/DOCX format. |
The CSV files use two columns:
Id: relative path to an image, for example./Train/.../IMG_4107.JPEGLabel: integer class id
Current CSV sizes:
| Split | Rows | Distinct labels in CSV |
|---|---|---|
| Train | 9,624 | 192 |
| Validation | 400 | 154 |
| Test | 351 | 109 |
The scripts expect the full dataset to exist under:
/content/drive/My Drive/Knives
Expected layout:
/content/drive/My Drive/Knives/
train.csv
val.csv
test.csv
Train/
Test/
Model_Checkpoints/
FinalPlots/
train.py prepends /content/drive/My Drive/Knives/ to the relative image paths in train.csv and val.csv. test.py reads /content/drive/My Drive/Knives/test.csv; if running locally instead of Colab, update the hard-coded paths in train.py, test.py, and, if needed, data.py.
The pinned dependencies are:
numpy==1.21.5
opencv_python_headless==4.7.0.72
pandas==1.4.4
Pillow==10.0.1
scikit_learn==1.0.2
timm==0.6.12
torch==1.12.1
torchvision==0.13.1
Install them with:
pip install -r requirements.txtCUDA is strongly recommended. The current scripts call .cuda() directly in several places, so CPU-only execution requires code changes.
The active settings are defined in config.py:
n_classes = 192
img_weight = 224
img_height = 224
batch_size = 16
epochs = 11
learning_rate = 0.00005The default model in train.py is:
model_variant_name = 'tf_efficientnet_b0'Other model variants are present as commented options, including:
densenet121densenet264tf_efficientnet_b6deit_tiny_patch16_224
DenseNet models are composed of dense blocks, where each layer receives feature maps from all preceding layers in the same block. The growth rate, k, controls how many new feature maps each layer contributes to the block, influencing model capacity and feature reuse.
Historical config snapshots are stored in Experiments/config (2).py, Experiments/config (3).py, and Experiments/config (4).py.
The experiments include hyperparameter optimisation around optimiser choice, learning rate, weight decay, and momentum.
- The learning rate, eta, determines the gradient descent step size during optimisation.
- L2 regularisation, controlled by weight decay lambda, encourages the models to learn more generalizable representations of knife images.
- Momentum was considered with coefficient values in the
[0.5, 0.9]range. - Momentum is integrated into the SGD optimiser to improve the convergence of stochastic gradient descent. During EfficientNet-B6 and DenseNet264 training, it influenced the learning process and helped the optimiser escape local minima.
The optimizer comparison tracks mAP progression over 10 epochs for Adam, RMSprop, and SGD.
SGD shows the fastest and most stable early convergence, reaching 0.58 mAP by epoch 2 and around 0.66-0.68 mAP by epochs 3-10. RMSprop also converges strongly, reaching 0.58 mAP by epoch 3 and stabilising near 0.68 mAP from epoch 4 onward.
Adam improves more slowly and less smoothly. It starts below 0.30 mAP until epoch 3, but eventually catches up and reaches similar final performance of around 0.68-0.69 mAP by epoch 10.
The scheduler comparison evaluates the best mAP values obtained with CosineAnnealingLR and StepLR under three learning rates: 0.01, 0.001, and 0.0001.
Both schedulers show similar performance, with the strongest results achieved at lr = 0.001, reaching approximately 0.68 mAP. The learning rate 0.01 performs noticeably worse for both schedulers, staying close to 0.60 mAP.
Overall, StepLR and CosineAnnealingLR behave comparably, while lower learning rates provide more stable and effective fine-tuning.
In the original Colab workflow:
python3 /content/drive/MyDrive/Knives/train.pyFrom the repository root, after adjusting dataset paths if needed:
python3 train.pyTraining behavior:
- Uses
knifeDatasetwith image resize to224 x 224. - Applies data augmentation during training: color jitter, random rotation, random vertical flip, and random horizontal flip.
- Uses ImageNet normalization for all splits.
- Creates a pretrained
timmmodel withnum_classes=192. - Uses Adam with cosine annealing learning-rate scheduling.
- Uses cross-entropy loss.
- Computes validation mAP@5 after each epoch.
- Saves model weights every 4 epochs using names like
Knife-Effb0-E4.pt. - Writes final training/validation loss and validation mAP plots under
FinalPlots/<model_variant_name>/.
test.py loads the test CSV, creates a test dataloader, restores model weights, and prints mAP:
python3 test.pyBy default it expects weights at:
logs/Knife-Effb0-E9.pt
Update this line in test.py if the checkpoint filename or location is different:
model.load_state_dict(torch.load('logs/Knife-Effb0-E9.pt'))The notebooks and experiment log include several recorded mAP values:
| Experiment note | Recorded test mAP |
|---|---|
| EfficientNet-B0, batch 32, 15 epochs, lr 0.0001 | 0.6180 |
| EfficientNet-B0, batch 64, 20 epochs, lr 0.001 | 0.6231 |
| EfficientNet-B0, batch 48, 20 epochs, lr 0.0005 | 0.6365 |
| EfficientNet-B6, batch 48, 40 epochs, lr 0.0005 | 0.6785 |
| Later EfficientNet run marked "try 60 epochs" | 0.7316 |
| DenseNet121, batch 64, 22 epochs, lr 0.0001 | 0.6433 |
| DenseNet121, batch 64, 32 epochs, lr 0.0001 | 0.6536 |
| DenseNet121, batch 32, 32 epochs, lr 0.0001 | 0.6829 |
| DenseNet121, batch 16, 36 epochs, lr 0.0001 | 0.6800 |
Experiments/%s_log_train.txt also records validation mAP during one run, reaching approximately 0.715 at epoch 16.
The experiment artifacts include two training-curve plots:
Training and Validation Loss over EpochsValidation Mean Average Precision (mAP) over Epochs
Observation 3: Slight rises were detected in validation loss during EfficientNet-B6 and DenseNet264 training. These rises were attributed to the use of a relatively high learning rate. The oscillations were expected, because modifying the models caused groups of knife images to be misclassified at a time, significantly lowering or raising the mAP.
When training the baseline EfficientNet-B0 model, the validation loss decreased during the first 5 epochs, then gradually reduced close to 0.
- The dataset images and trained model weights are not tracked in this repository.
- Several paths are hard-coded to Google Drive/Colab locations.
train.pyimportsModifiedAlexNetfromalexNetModel, butalexNetModel.pyis not present in the repository. The import must be removed/commented or the missing module must be restored before the active script can run.test.pyexpects a checkpoint file inlogs/, but no checkpoint files are included.utils.save_checkpoint()references config attributes such asweights,model_name, andbest_modelsthat are not defined in the activeconfig.py; this helper is not used by the current training loop.- The active metric variable is named
map, which shadows Python's built-inmap.
Project reports are stored in Paper/, and experiment assets are stored in Experiments/. The image plots in Experiments/ show training/validation loss and validation mAP curves from a recorded run.