| --- |
| license: apache-2.0 |
| base_model: distilbert-base-uncased |
| tags: |
| - text-classification |
| - multi-label-classification |
| - emotion-detection |
| - distilbert |
| - pytorch |
| datasets: |
| - go_emotions |
| language: |
| - en |
| metrics: |
| - f1 |
| pipeline_tag: text-classification |
| --- |
| |
| # EmotiCare — Multi-Label Emotion Classifier |
|
|
| EmotiCare is a fine-tuned [DistilBERT](https://huggingface.co/distilbert-base-uncased) 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](https://huggingface.co/datasets/go_emotions) 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. |
|
|
| ## Emotions |
|
|
| The model classifies text into 28 emotions: |
|
|
| `admiration` · `amusement` · `anger` · `annoyance` · `approval` · `caring` · `confusion` · `curiosity` · `desire` · `disappointment` · `disapproval` · `disgust` · `embarrassment` · `excitement` · `fear` · `gratitude` · `grief` · `joy` · `love` · `nervousness` · `optimism` · `pride` · `realization` · `relief` · `remorse` · `sadness` · `surprise` · `neutral` |
|
|
| ## Model Details |
|
|
| | Property | Value | |
| |---|---| |
| | Base model | `distilbert-base-uncased` | |
| | Architecture | DistilBertForSequenceClassification | |
| | Task | Multi-label text classification | |
| | Dataset | GoEmotions (simplified, 43,410 train samples) | |
| | Training epochs | 3 | |
| | Max sequence length | 512 tokens | |
| | Framework | PyTorch + 🤗 Transformers | |
|
|
| ## Evaluation Results |
|
|
| 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 |
| from transformers import pipeline |
| import torch |
| |
| classifier = pipeline( |
| "text-classification", |
| model="BruceIC/emoticare", # replace with your HF repo path |
| tokenizer="BruceIC/emoticare", |
| top_k=None, # return scores for all labels |
| device=0 if torch.cuda.is_available() else -1, |
| ) |
| |
| text = "I can't believe how thoughtful that was, I'm so touched." |
| results = classifier(text) |
| |
| # Filter to emotions above a confidence threshold |
| threshold = 0.3 |
| detected = [r for r in results[0] if r["score"] > threshold] |
| for emotion in sorted(detected, key=lambda x: -x["score"]): |
| print(f"{emotion['label']:<20} {emotion['score']:.3f}") |
| ``` |
|
|
| **Example output:** |
| ``` |
| gratitude 0.847 |
| admiration 0.612 |
| love 0.431 |
| ``` |
|
|
| --- |
|
|
| ### Manual inference (more control) |
|
|
| ```python |
| import torch |
| import torch.nn.functional as F |
| from transformers import DistilBertTokenizer, DistilBertForSequenceClassification |
| |
| model_name = "BruceIC/emoticare" # replace with your HF repo path |
| |
| tokenizer = DistilBertTokenizer.from_pretrained(model_name) |
| model = DistilBertForSequenceClassification.from_pretrained(model_name) |
| model.eval() |
| |
| def predict_emotions(text: str, threshold: float = 0.3): |
| inputs = tokenizer( |
| text, |
| return_tensors="pt", |
| truncation=True, |
| max_length=512, |
| padding=True, |
| ) |
| with torch.no_grad(): |
| logits = model(**inputs).logits |
| probs = torch.sigmoid(logits).squeeze() # sigmoid for multi-label |
| |
| emotions = model.config.id2label |
| results = [ |
| {"label": emotions[i], "score": float(probs[i])} |
| for i in range(len(emotions)) |
| if float(probs[i]) > threshold |
| ] |
| return sorted(results, key=lambda x: -x["score"]) |
| |
| # Example |
| print(predict_emotions("I'm so proud of everything we've built together!")) |
| ``` |
|
|
| --- |
|
|
| ### Batch inference |
|
|
| ```python |
| texts = [ |
| "I'm terrified of what might happen next.", |
| "This is the best day of my life!", |
| "I don't really feel anything about it.", |
| ] |
| |
| inputs = tokenizer( |
| texts, |
| return_tensors="pt", |
| truncation=True, |
| max_length=512, |
| padding=True, |
| ) |
| |
| with torch.no_grad(): |
| logits = model(**inputs).logits |
| |
| probs = torch.sigmoid(logits) # shape: (batch_size, 28) |
| threshold = 0.3 |
| |
| for i, text in enumerate(texts): |
| detected = [ |
| model.config.id2label[j] |
| for j in range(28) |
| if probs[i][j] > threshold |
| ] |
| print(f"Text: {text}") |
| print(f"Emotions: {', '.join(detected) or 'none above threshold'}\n") |
| ``` |
|
|
| ## Training Details |
|
|
| - **Base model:** `distilbert-base-uncased` |
| - **Dataset:** [go_emotions](https://huggingface.co/datasets/go_emotions) (simplified config) |
| - **Loss function:** Binary Cross-Entropy (multi-label) |
| - **Optimizer:** AdamW with linear warmup + decay |
| - **Learning rate:** 2e-5 (peak) |
| - **Batch size:** 16 |
| - **Epochs:** 3 |
| - **Best checkpoint:** step 8142 (epoch 3) |
|
|
| ## Limitations |
|
|
| - 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 |
| @inproceedings{demszky-etal-2020-goemotions, |
| title = {{GoEmotions}: A Dataset of Fine-Grained Emotions}, |
| author = {Demszky, Dorottya and Movshovitz-Attias, Dana and Ko, Jeongwook |
| and Cowen, Alan and Nemade, Gaurav and Ravi, Sujith}, |
| booktitle = {Proceedings of the 58th Annual Meeting of the Association for |
| Computational Linguistics}, |
| year = {2020}, |
| } |
| ``` |
|
|