Moodalyx BiGRU · dair-ai/emotion · 6 labels Connecting…

Natural language processing · recurrent networks · multi-class classification

Predicting emotion labels from short English text

A two-layer bidirectional GRU, trained on 16,000 labelled sentences from the dair-ai/emotion dataset, assigns one of six labels: sadness, joy, love, anger, fear or surprise. Type a sentence to see the full probability distribution from the deployed model.

What this model does and does not do

It predicts which of the dataset's six labels a sentence most resembles. It does not measure anyone's actual emotional or psychological state, has no “neutral” option, and is most reliable on text similar to its training data (short, first-person sentences such as “i feel …”).

Analyse text

Each request goes to POST /predict, which cleans the text, tokenises it, pads it to 50 tokens and runs the BiGRU.

Up to 2,000 characters. Only the first 50 tokens are used by the model. Ctrl/⌘ + Enter to analyse.
Example sentences from the training notebook (cell 39) i

Prediction

—
No prediction yet Enter a sentence or pick an example to see all six class probabilities.

Evaluation

Figures marked re-evaluated were computed from the shipped model on the 2,000-sentence test split by evaluation/evaluate_artifact.py, using the same cleaning as the API. Figures marked notebook are copied from the training notebook's saved outputs.

How the model works

  1. 1 · Cleanlower-case, drop apostrophes, replace non-alphanumerics with spaces, collapse whitespacemain.preprocess_text
  2. 2 · TokeniseKeras Tokenizer: 10,000 most frequent training words; others become <unk>tokenizer.pkl
  3. 3 · Padpost-pad or post-truncate to exactly 50 token idspad_sequences
  4. 4 · Encode300-d embedding → BiGRU(128) → dropout → BiGRU(64) → dropoutBiGRU_Model.keras
  5. 5 · Classifydense softmax over 6 labels; the API returns all probabilities and the arg-maxPOST /predict

Training setup

notebook cells 14–33
Data
dair-ai/emotion: 16,000 train / 2,000 test sentences (Saravia et al., 2018)
Objective
Sparse categorical cross-entropy with balanced class weights
Optimiser
Adam (Keras defaults), batch size 32, up to 20 epochs
Stopping
Early stopping on val_loss, patience 3, best weights restored (stopped after epoch 8; best epoch 5)
Parameters
3,454,662 trainable
Serving
FastAPI + TensorFlow/Keras, model and tokenizer loaded once at start-up

Limitations

  1. Optimistic test score. The notebook passed the test split as validation_data for early stopping, so the test set influenced model selection. The dataset's separate validation split was not used.
  2. Narrow domain. Training sentences are short English posts that mostly begin with “i feel …”. Other writing styles, sarcasm, negation and long text are not represented well.
  3. No neutral class. Every input is forced into one of six emotions, including factual or neutral sentences.
  4. Imbalanced labels. Surprise (66 test sentences) and love (159) have the lowest F1; class weights only partly compensate.
  5. Confidence is not certainty. High softmax probabilities can still be wrong — see the high-confidence errors above.
  6. Not a psychological instrument. Do not use the output to make decisions about people.

Reproduce

cd DL/EMOTION_TEXT_DL_NLP
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --port 8000
# optional: regenerate static/data/evaluation.json
pip install -r evaluation/requirements-eval.txt
python evaluation/evaluate_artifact.py