Fine-Grained Emotion Classification
RoBERTa 0.5296 macro F1 · BiLSTM 0.3714 · TF-IDF 0.3751
Built with
Sentiment analysis usually means positive, negative or neutral. GoEmotions is harder: 27 fine-grained emotions where the boundaries blur, comments carry more than one feeling at once, and the classes are heavily imbalanced.
This was a semester project by a group of three. We worked up through three models (a TF-IDF baseline, a BiLSTM over GloVe embeddings, and a fine-tuned RoBERTa) with per-class threshold tuning on top, because a single global threshold on a heavily imbalanced multi-label problem quietly optimises for the common classes and abandons the rare ones.
The result worth recording is that the BiLSTM lost. Macro F1 came in at 0.3714 against 0.3751 for the TF-IDF baseline. Fractionally behind, after considerably more work. GloVe's vectors are trained on Wikipedia and newswire, and Reddit comments are informal, abbreviated and full of vocabulary those vectors never saw, so the embeddings carried less signal than expected. The comments are also short, which leaves sequential modelling with very little sequence to model. Counting words was already capturing most of what was there.
Fine-tuned RoBERTa is the jump, at 0.5296. What transfers is not the architecture but having been pretrained on a corpus messy enough to resemble the target. The clearest evidence is in the rare classes: the BiLSTM scores exactly 0.00 on grief and relief, never learning them at all, while RoBERTa reaches 0.44 and 0.38 from the same handful of examples.
For scale, a majority-class baseline that answers "neutral" every time scores 0.0177, because neutral has around 18,000 training samples and grief has about 100.
What this does not show
- A group project of three: Ahzam Afaq, Hamza Tarazi and me.
- Semester coursework. The interesting finding is where the models fail, not a leaderboard score.
- Run in a Colab notebook, so it is not packaged for clean reproduction.