File size: 5,811 Bytes
e93b079 142ebfc e93b079 142ebfc c161bc5 142ebfc c161bc5 142ebfc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | ---
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},
}
```
|