Four model families, one documented data pipeline, and a compact TensorFlow Lite export, evaluated on the Oxford 102 Flowers dataset.
| Metric | Value |
|---|---|
| Flower classes | 102 |
| Source images | 8,189 |
| Images after duplicate handling | 8,185 |
| Models evaluated | 4 |
| Best test accuracy | 95.71% |
| Optimized TFLite size | 2.53 MB |
This repository documents a complete flower classification study: dataset inspection, duplicate detection, class-aware splitting, augmentation, class weighting, transfer learning, CNN feature extraction for a classical classifier, test-set evaluation, and TensorFlow Lite conversion. MobileNetV2 produced the strongest recorded test result and was selected for conversion.
The repository contains the research notebooks and export artifacts. It does not contain an Android application or evidence of a production deployment.
.
├── benchmark_images/ # Ten small reference images
├── docs/images/ # Public figures copied from notebook outputs
├── flower_dataset_preparation/
│ ├── flower_dataset_preparation.ipynb # Data preparation, training, and evaluation
│ ├── model_to_tflite.ipynb # TensorFlow Lite conversion and validation
│ └── labels.txt # 102 class labels
├── flower_tflite_preparation/
│ ├── labels.txt # Labels packaged with the final export
│ └── mobilenetv2_optimized.tflite # Optimized MobileNetV2 model
├── .gitignore
├── LICENSE
└── README.md
Downloaded data, split image folders, Keras models, serialized predictions, and intermediate SavedModel files are intentionally kept local and excluded from normal Git tracking.
The study uses the Oxford 102 Flowers dataset, which contains 8,189 images across 102 flower categories. The project uses the official image labels and split metadata files, then creates its own class-aware 60/10/30 split after duplicate handling.
The integrity pass found four duplicate groups. One repeated file from each group was moved out of the training image pool, leaving 8,185 images:
| Split | Images | Recorded share |
|---|---|---|
| Train | 4,872 | 59.49% |
| Validation | 774 | 9.45% |
| Test | 2,539 | 31.01% |
Small differences from the target ratios come from integer rounding within each class. Every class is represented in all three generated splits.
Class counts before splitting show the dataset's substantial imbalance.
Class aware train, validation, and test allocation after duplicate handling.
Dataset images are not redistributed in this repository. Download 102flowers.tgz, imagelabels.mat, and setid.mat from the official dataset page and place them in raw_data/ before running the preparation notebook.
All models use 224 × 224 RGB inputs. The Keras generators apply 1/255 rescaling to every split. Training data additionally uses:
- rotations up to 15 degrees;
- width and height shifts of 10%;
- shear up to 10% and zoom up to 20%;
- horizontal flips;
- brightness scaling from 0.8 to 1.2;
- nearest-neighbour fill for transformed pixels.
NumPy, TensorFlow, and generator seeds are set to 42. Balanced class weights are computed from the training labels and passed to the neural network training runs.
A pretrained ImageNet MobileNetV2 backbone removes its classification head, applies global-average pooling, and produces fixed image feature vectors. XGBoost then performs classification across 102 classes. RandomizedSearchCV evaluates three configurations with two-fold cross-validation; the recorded best configuration uses 150 estimators, depth 4, and learning rate 0.1.
The ImageNet backbone starts frozen beneath global-average pooling and a dense classifier with 128 units. A second phase unfreezes the model and continues fine-tuning with a learning rate of 1e-5. Early stopping, learning-rate reduction, augmentation, and class weighting are used.
The pretrained backbone remains frozen beneath global-average pooling, a dense layer with 256 units, 50% dropout, and the final softmax layer for 102 classes. The retained experiment is the base-training run; attempted fine-tuning was removed from the final workflow after it failed to improve validation behaviour.
The pretrained backbone starts frozen beneath global-average pooling, 20% dropout, and a softmax layer for 102 classes. The selected model then undergoes complete fine-tuning at 1e-5, using early stopping, learning-rate reduction, augmentation, and class weighting.
Neural models use categorical cross-entropy and report accuracy plus macro and weighted precision, recall, and F1. XGBoost is evaluated with multiclass log loss during fitting and the same classification metrics afterward. Final comparisons below use the reserved test split of 2,539 images.
Training and inference times are measurements from the recorded notebook run, not benchmarks that are independent of hardware. Model sizes are the serialized artifacts measured by the notebook.
| Model | Test accuracy | Weighted F1 |
|---|---|---|
| XGBoost | 79.80% | 79.39% |
| VGG16 | 83.42% | 83.41% |
| NASNetMobile | 80.66% | 80.50% |
| MobileNetV2 | 95.71% | 95.72% |
| Model | Training time | Inference per image | Model size |
|---|---|---|---|
| XGBoost | 483.13 s | 0.000016 s | 13.52 MB |
| VGG16 | 21,641.87 s | 0.055700 s | 169.40 MB |
| NASNetMobile | 2,821.40 s | 0.008552 s | 22.30 MB |
| MobileNetV2 | 11,841.52 s | 0.005182 s | 27.74 MB |
The original notebook comparison uses a logarithmic axis because the four recorded measures span very different scales and units.
Base-training accuracy and loss curves retained in the notebook output; the separate fine-tuning phase is not plotted here.
The selected MobileNetV2 model is exported through SavedModel and converted to TensorFlow Lite. The recorded artifact sizes are:
| Artifact | Size |
|---|---|
| Keras MobileNetV2 | 27.74 MB |
| Optimized TensorFlow Lite | 2.53 MB |
| Reduction | 25.22 MB |
The conversion notebook evaluates the TFLite artifact again on all 2,539 test images. Its displayed macro and weighted precision, recall, and F1 values round to 0.95.
No mobile runtime, latency measurement from a phone, or production deployment is included here.
The notebooks rely on relative paths. Open Jupyter with flower_dataset_preparation/ as the working directory; moving or launching the notebooks from another level can break paths such as ../flower_dataset_preparation/split_data.
Run order:
flower_dataset_preparation.ipynbmodel_to_tflite.ipynb
No dependency lockfile is present. The original project notes record a TensorFlow 2.19.0 environment for the main notebook. The TFLite notebook's saved runtime output records Python 3.10.18, TensorFlow 2.14.0, NumPy 1.23.5, pandas 2.3.1, and scikit-learn 1.7.1. Both notebook metadata blocks identify Python 3.12.7, so the runtime and metadata should be reconciled before claiming a single fully reproducible environment.
The generated .keras, SavedModel, pickle, dataset, and intermediate conversion files are excluded because they are large or reproducible local artifacts. In particular, vgg16_model.keras is approximately 169.40 MB and exceeds GitHub's normal limit for individual files. No external download is currently provided for these local model files.
- The dataset is imbalanced, with some categories containing far more examples than others.
- The custom split differs from the official Oxford split and should be considered when comparing results with other studies.
- The saved comparison reflects one recorded training environment; timings will vary by hardware and software stack.
- The repository does not include a dependency lockfile or a tested setup that uses a single command.
- No confusion matrix for each class or systematic catalogue of commonly confused flower pairs is published, so claims about errors for specific classes are intentionally omitted.
- The work is a research and demonstration project, not a validated production system.
Fatemeh Sabourinia and Alireza Zaeri
This project is licensed under the MIT License. See the LICENSE file for details.




