EmotiCare is a fine-tuned DistilBERT model for multi-label emotion detection in English text. Given a sentence, it predicts one or more emotions from 28 categories drawn from the GoEmotions dataset.
It is designed for use in applications that need nuanced, fine-grained emotion understanding — such as mental health tools, sentiment dashboards, chatbots, and content moderation systems.
Evaluated on the GoEmotions test set (5,427 examples):
Metric
Score
F1 Macro
0.4019
F1 Micro
0.5702
Eval Loss
0.0843
Note: Multi-label emotion classification on GoEmotions is a challenging task due to class imbalance and overlapping emotions. F1 Micro of ~0.57 is competitive with similar fine-tuned DistilBERT baselines.
Inference
Using the 🤗 pipeline (recommended)
python
1from transformers import pipeline
2import torch
34classifier = pipeline(5"text-classification",6 model="BruceIC/emoticare",# replace with your HF repo path7 tokenizer="BruceIC/emoticare",8 top_k=None,# return scores for all labels9 device=0if torch.cuda.is_available()else-1,10)1112text ="I can't believe how thoughtful that was, I'm so touched."13results = classifier(text)1415# Filter to emotions above a confidence threshold16threshold =0.317detected =[r for r in results[0]if r["score"]> threshold]18for emotion insorted(detected, key=lambda x:-x["score"]):19print(f"{emotion['label']:<20}{emotion['score']:.3f}")
Example output:
gratitude 0.847
admiration 0.612
love 0.431
Manual inference (more control)
python
1import torch
2import torch.nn.functional as F
3from transformers import DistilBertTokenizer, DistilBertForSequenceClassification
45model_name ="BruceIC/emoticare"# replace with your HF repo path67tokenizer = DistilBertTokenizer.from_pretrained(model_name)8model = DistilBertForSequenceClassification.from_pretrained(model_name)9model.eval()1011defpredict_emotions(text:str, threshold:float=0.3):12 inputs = tokenizer(13 text,14 return_tensors="pt",15 truncation=True,16 max_length=512,17 padding=True,18)19with torch.no_grad():20 logits = model(**inputs).logits
21 probs = torch.sigmoid(logits).squeeze()# sigmoid for multi-label2223 emotions = model.config.id2label
24 results =[25{"label": emotions[i],"score":float(probs[i])}26for i inrange(len(emotions))27iffloat(probs[i])> threshold
28]29returnsorted(results, key=lambda x:-x["score"])3031# Example32print(predict_emotions("I'm so proud of everything we've built together!"))
Batch inference
python
1texts =[2"I'm terrified of what might happen next.",3"This is the best day of my life!",4"I don't really feel anything about it.",5]67inputs = tokenizer(8 texts,9 return_tensors="pt",10 truncation=True,11 max_length=512,12 padding=True,13)1415with torch.no_grad():16 logits = model(**inputs).logits
1718probs = torch.sigmoid(logits)# shape: (batch_size, 28)19threshold =0.32021for i, text inenumerate(texts):22 detected =[23 model.config.id2label[j]24for j inrange(28)25if probs[i][j]> threshold
26]27print(f"Text: {text}")28print(f"Emotions: {', '.join(detected)or'none above threshold'}\n")
Trained on Reddit comments — performance may degrade on formal text, non-native English, or very short inputs.
Some rare emotions (grief, pride, relief) have limited training examples and lower per-class F1.
Outputs are probabilities; the optimal threshold (default 0.3) may need tuning for your use case.
Citation
If you use this model, please cite the GoEmotions dataset:
bibtex
1@inproceedings{demszky-etal-2020-goemotions,
2 title = {{GoEmotions}: A Dataset of Fine-Grained Emotions},
3 author = {Demszky, Dorottya and Movshovitz-Attias, Dana and Ko, Jeongwook
4 and Cowen, Alan and Nemade, Gaurav and Ravi, Sujith},
5 booktitle = {Proceedings of the 58th Annual Meeting of the Association for
6 Computational Linguistics},
7 year = {2020},
8}