File size: 5,987 Bytes
5d6d03c 97fcd2a 5d6d03c 97fcd2a 5d6d03c |
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 194 195 196 197 |
"""
Emotion Detection App - Hugging Face Spaces
Multi-label emotion classification using DeBERTa-v3-base
"""
import gradio as gr
import torch
import torch.nn as nn
from transformers import AutoTokenizer, AutoModel
import numpy as np
# Configuration
MODEL_NAME = "microsoft/deberta-v3-base"
EMOTION_LABELS = ['anger', 'fear', 'joy', 'sadness', 'surprise']
MAX_LENGTH = 160
DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Model Architecture
class EmotionClassifier(nn.Module):
"""DeBERTa-v3-base for multi-label emotion classification"""
def __init__(self, model_name, num_labels=5, dropout=0.1):
super().__init__()
self.encoder = AutoModel.from_pretrained(model_name)
hidden_size = self.encoder.config.hidden_size
self.dropout = nn.Dropout(dropout)
self.classifier = nn.Linear(hidden_size, num_labels)
def forward(self, input_ids, attention_mask):
outputs = self.encoder(
input_ids=input_ids,
attention_mask=attention_mask
)
pooled_output = outputs.last_hidden_state[:, 0]
pooled_output = self.dropout(pooled_output)
logits = self.classifier(pooled_output)
return logits
# Load model and tokenizer
print("Loading model...")
print(f"Loading tokenizer from {MODEL_NAME}...")
tokenizer = AutoTokenizer.from_pretrained(
MODEL_NAME,
use_fast=True,
trust_remote_code=False
)
print("β Tokenizer loaded")
print(f"Initializing model architecture...")
model = EmotionClassifier(MODEL_NAME, len(EMOTION_LABELS)).to(DEVICE)
print("β Model architecture created")
# Load trained weights
try:
model.load_state_dict(torch.load('best_deberta_model.pth', map_location=DEVICE))
print("β Model loaded successfully!")
except Exception as e:
print(f"Warning: Could not load model weights: {e}")
print("Using randomly initialized model (for testing)")
model.eval()
def predict_emotions(text):
"""
Predict emotions for input text
Args:
text (str): Input text to analyze
Returns:
dict: Emotion probabilities and predictions
"""
if not text or len(text.strip()) == 0:
return {
"error": "Please enter some text to analyze",
"probabilities": {},
"detected_emotions": []
}
# Tokenize
encoding = tokenizer(
text,
max_length=MAX_LENGTH,
padding='max_length',
truncation=True,
return_tensors='pt'
)
input_ids = encoding['input_ids'].to(DEVICE)
attention_mask = encoding['attention_mask'].to(DEVICE)
# Predict
with torch.no_grad():
logits = model(input_ids, attention_mask)
probabilities = torch.sigmoid(logits).cpu().numpy()[0]
# Create results
results = {}
detected_emotions = []
for label, prob in zip(EMOTION_LABELS, probabilities):
results[label.capitalize()] = float(prob)
if prob > 0.5:
detected_emotions.append(f"{label.capitalize()} ({prob:.1%})")
# Sort by probability
results = dict(sorted(results.items(), key=lambda x: x[1], reverse=True))
return results, ", ".join(detected_emotions) if detected_emotions else "No strong emotions detected"
# Example texts
examples = [
["I just got accepted into my dream university! I can't believe it!"],
["I'm so worried about the exam tomorrow. I haven't studied enough."],
["This is the worst day of my life. Everything went wrong."],
["I can't believe they did this to me. I'm furious!"],
["Wow! I never expected that to happen!"],
["The sunset today was beautiful. It made me feel peaceful."],
["I'm frustrated with this project but also excited about the possibilities."]
]
# Create Gradio interface
with gr.Blocks(theme=gr.themes.Soft(), title="Emotion Detection") as demo:
gr.Markdown(
"""
# π Multi-Label Emotion Detection
Detect multiple emotions in text using **DeBERTa-v3-base** fine-tuned for emotion classification.
**Emotions detected**: Anger, Fear, Joy, Sadness, Surprise
This model can detect multiple emotions simultaneously in a single text.
"""
)
with gr.Row():
with gr.Column():
text_input = gr.Textbox(
label="Enter text to analyze",
placeholder="Type or paste your text here...",
lines=5
)
analyze_btn = gr.Button("π Analyze Emotions", variant="primary", size="lg")
gr.Markdown("### π‘ Try these examples:")
gr.Examples(
examples=examples,
inputs=text_input,
label="Click an example to try it"
)
with gr.Column():
gr.Markdown("### π Results")
detected_output = gr.Textbox(
label="Detected Emotions",
placeholder="Results will appear here...",
lines=2
)
prob_output = gr.Label(
label="Emotion Probabilities",
num_top_classes=5
)
gr.Markdown(
"""
---
**How it works:**
- Probabilities above 50% indicate detected emotions
- Multiple emotions can be present in the same text
- Higher probability = stronger emotion signal
**Model:** DeBERTa-v3-base (184M parameters)
**Performance:** F1 Score ~0.85 on validation set
"""
)
# Connect the button
analyze_btn.click(
fn=predict_emotions,
inputs=text_input,
outputs=[prob_output, detected_output]
)
# Also trigger on text input (Enter key)
text_input.submit(
fn=predict_emotions,
inputs=text_input,
outputs=[prob_output, detected_output]
)
# Launch
if __name__ == "__main__":
demo.launch()
|