Genre Categorization for Goodreads Reviews via Fine-Tuned DistilBERT
This project details an end-to-end MLOps workflow designed to classify Goodreads book reviews into seven distinct genres using a fine-tuned distilbert-base-cased architecture. The implementation showcases standard MLOps practices, including GPU-accelerated training via Kaggle, experiment logging with Weights & Biases, and model hosting on the Hugging Face Hub.
The core task is multi-class text classification: analyzing unstructured text from Goodreads reviews to determine the corresponding book genre. The model categorizes inputs into one of seven target genres:
Poetry
Comics & Graphic
Fantasy & Paranormal
History & Biography
Mystery, Thriller & Crime
Romance
Young Adult
Note: The primary aim of this assignment is to establish a robust, tracked, and easily deployable machine learning engineering pipeline rather than optimizing raw predictive accuracy.
Dataset
Origin: Data is sourced from the UCSD Goodreads Book Graph, utilizing individual genre files in .json.gz format.
Sampling Strategy: Subsets of reviews were extracted across all genres to accommodate training constraints on free tier hardware.
Data Partitioning: A stratified 80/20 split was applied to separate training and evaluation sets while maintaining balanced class representations.
Features: The review_text column serves as the input sequence, capped at a maximum length of 512 tokens during tokenization.
Pipeline Architecture
Raw Goodreads Reviews (7 genres, UCSD Book Graph)
│
▼
Data Loading & Sampling
│
▼
DistilBERT Tokenization
(distilbert-base-cased, max_length=512)
│
▼
Fine-Tuning on Kaggle GPU (T4)
(HuggingFace Trainer API, 3 epochs)
│
├──► Experiment Tracking (Weights & Biases)
│ - Loss, Accuracy, F1 per epoch
│ - Hyperparameters logged
│ - Eval report as W&B Artifact
▼
Evaluation on Test Set
(Accuracy, F1, Classification Report)
│
▼
Model Deployment → Hugging Face Hub
(publicly accessible for inference)
Model Architecture
Component
Detail
Base model
distilbert-base-cased
Task head
DistilBertForSequenceClassification
Number of labels
7
Max token length
512
Framework
HuggingFace Transformers + PyTorch
Why DistilBERT?
DistilBERT is a distilled (compressed) version of BERT that retains ~97% of BERT's language understanding while being 40% smaller and 60% faster. For an MLOps assignment focused on workflow rather than state-of-the-art accuracy, DistilBERT offers the ideal balance between performance and training speed on free Kaggle GPU resources. Its well-documented HuggingFace integration also makes it straightforward to load, fine-tune, and deploy within a single pipeline.
Training Configuration
Hyperparameter
Value
Epochs
3
Train batch size
16
Eval batch size
32
Learning rate
3e-5
Warmup steps
100
Weight decay
0.01
Logging steps
50
Evaluation strategy
Every epoch
Optimizer
AdamW (HuggingFace default)
Training platform
Kaggle Notebook (GPU T4)
MLOps Components
1. Experiment Tracking — Weights & Biases
All runs logged automatically via report_to="wandb" in TrainingArguments
Tracks: training loss, eval loss, accuracy, F1 score per epoch
Hyperparameters captured in W&B config for full reproducibility
Final evaluation report saved as a versioned W&B Artifact
2. Training Platform — Kaggle Notebooks
Hardware: GPU T4 (free tier, 30 hrs/week)
Internet enabled for HuggingFace model downloads and Hub push
API credentials stored securely via Kaggle Secrets (WANDB_API_KEY_2, HF_TOKEN_2)
Zero hardcoded credentials in any code
3. Model Deployment — Hugging Face Hub
Fine-tuned model and tokenizer pushed to HuggingFace Hub
Publicly accessible — anyone can load and run inference with one line:
python
1from transformers import pipeline
2classifier = pipeline("text-classification", model="Rodosi/mlops-distilbert-workflow")3result = classifier("This fantasy novel had incredible world-building and magic systems.")4print(result)
Results
MetricScoreAccuracy | 0.6013 |
Weighted F1 | 0.5979 |
Eval Loss | 2.2483 |
What the W&B Charts Showed
Training loss decreased steadily across all 3 epochs — model was learning
Validation loss tracked training loss closely — no significant overfitting
Accuracy and F1 improved each epoch, confirming the fine-tuning was effective
Project Structure
mlops-assignment2/
├── mlops-assignment2.ipynb # Kaggle notebook — full training pipeline
├── train_pipeline.py # Python script exported from Kaggle notebook
├── requirements.txt # All Python dependencies
└── README.md # This file