-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/dl add emotion detection enhancements #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7193f40
56a5d15
3c73dd8
3a5e7d9
6db18df
2d51cfc
b9ac502
ff3bbb9
6054ffc
bfa15ba
47365ce
6f73ac6
fa1a1dd
4c5e9d2
fddb258
19e47a3
a3a8c6e
04436cb
ca09ca1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,186 @@ | ||
| # SAMO-DL Emotion Detection Configuration | ||
| # Optimized parameters for journal entry emotion analysis | ||
|
|
||
| # Model Configuration | ||
| model: | ||
| name: "bert-base-uncased" # Robust BERT model for emotion understanding | ||
| device: null # Auto-detect (CPU/GPU) | ||
|
|
||
| # Emotion Detection Parameters | ||
| emotion_detection: | ||
| # Number of emotion categories (27 GoEmotions + neutral) | ||
| num_emotions: 28 | ||
|
|
||
| # Prediction threshold for binary classification | ||
| prediction_threshold: 0.6 # Updated from 0.5 for better calibration | ||
|
|
||
| # Temperature scaling for calibrated predictions | ||
| temperature: 1.0 | ||
|
|
||
| # Top-k emotions to return per prediction | ||
| top_k: 5 | ||
|
|
||
| # Model Architecture | ||
| architecture: | ||
| # BERT configuration | ||
| hidden_dropout_prob: 0.3 # Dropout for BERT hidden layers | ||
| attention_probs_dropout_prob: 0.3 # Dropout for attention layers | ||
|
|
||
| # Classification head configuration | ||
| classifier_dropout_prob: 0.5 # Dropout for classification layers | ||
|
|
||
| # Freezing strategy | ||
| freeze_bert_layers: 6 # Number of BERT layers to freeze initially | ||
|
|
||
| # Class balancing | ||
| use_class_weights: true # Enable class weight balancing | ||
|
|
||
| # Training Configuration | ||
| training: | ||
| # Batch sizes | ||
| train_batch_size: 16 | ||
| eval_batch_size: 32 | ||
|
|
||
| # Learning rates | ||
| bert_learning_rate: 2e-5 # Lower LR for BERT (fine-tuning) | ||
| classifier_learning_rate: 5e-4 # Higher LR for classification head | ||
|
|
||
| # Training epochs | ||
| num_epochs: 10 | ||
| warmup_steps: 100 | ||
|
|
||
| # Gradient settings | ||
| max_grad_norm: 1.0 | ||
| gradient_accumulation_steps: 1 | ||
|
|
||
| # Early stopping | ||
| early_stopping_patience: 3 | ||
| early_stopping_threshold: 0.01 | ||
|
|
||
| # Data Processing | ||
| data: | ||
| # Text processing | ||
| max_length: 512 # Maximum sequence length | ||
| truncation: true | ||
| padding: "max_length" | ||
|
|
||
| # Data augmentation | ||
| enable_augmentation: false # Disable for now, can be enabled later | ||
|
|
||
| # Validation split | ||
| validation_split: 0.2 | ||
| test_split: 0.1 | ||
|
|
||
| # Evaluation Configuration | ||
| evaluation: | ||
| # Metrics to compute | ||
| metrics: | ||
| - "precision" | ||
| - "recall" | ||
| - "f1_micro" | ||
| - "f1_macro" | ||
| - "accuracy" | ||
|
|
||
| # Evaluation threshold (lowered to capture more predictions) | ||
| threshold: 0.2 | ||
|
|
||
| # Top-k evaluation | ||
| top_k_evaluation: true | ||
| top_k_values: [1, 3, 5] | ||
|
|
||
| # Logging and Monitoring | ||
| logging: | ||
| level: "INFO" | ||
| log_interval: 100 # Log every N steps | ||
| save_interval: 1000 # Save checkpoint every N steps | ||
|
|
||
| # TensorBoard logging | ||
| enable_tensorboard: true | ||
| log_dir: "logs/emotion_detection" | ||
|
|
||
| # Model Saving | ||
| model_saving: | ||
| # Save directory | ||
| save_dir: "models/emotion_detection" | ||
|
|
||
| # Save best model based on metric | ||
| save_best_metric: "f1_macro" | ||
|
|
||
| # Save checkpoints | ||
| save_checkpoints: true | ||
| checkpoint_interval: 1 # Save every N epochs | ||
|
|
||
| # Performance Optimization | ||
| performance: | ||
| # Mixed precision training | ||
| use_amp: true # Automatic Mixed Precision | ||
|
|
||
| # Data loading | ||
| num_workers: 4 | ||
| pin_memory: true | ||
|
|
||
| # Memory optimization | ||
| gradient_checkpointing: false # Can be enabled for memory savings | ||
|
|
||
| # Inference optimization | ||
| use_torchscript: false # Can be enabled for faster inference | ||
|
|
||
| # SAMO-Specific Optimizations | ||
| samo_optimizations: | ||
| # Journal entry specific settings | ||
| journal_entry_mode: true | ||
|
|
||
| # Emotional context awareness | ||
| context_awareness: true | ||
|
|
||
| # Multi-label prediction | ||
| multi_label_mode: true | ||
|
|
||
| # Confidence calibration | ||
| calibration_enabled: true | ||
|
|
||
| # Emotion intensity scaling | ||
| intensity_scaling: true | ||
|
|
||
| # Error Handling | ||
| error_handling: | ||
| # Retry settings | ||
| max_retries: 3 | ||
| retry_delay: 1.0 | ||
|
|
||
| # Fallback behavior | ||
| fallback_to_cpu: true | ||
| graceful_degradation: true | ||
|
|
||
| # Logging errors | ||
| log_errors: true | ||
| error_log_file: "logs/emotion_detection_errors.log" | ||
|
|
||
| # Security and Privacy | ||
| security: | ||
| # Input sanitization | ||
| sanitize_input: true | ||
|
|
||
| # Output filtering | ||
| filter_sensitive_emotions: false # Can be enabled for privacy | ||
|
|
||
| # Rate limiting | ||
| rate_limit_requests: 1000 # Requests per minute | ||
|
|
||
| # Data privacy | ||
| anonymize_predictions: false # Can be enabled for privacy | ||
|
|
||
| # Development and Debugging | ||
| development: | ||
| # Debug mode | ||
| debug_mode: false | ||
|
|
||
| # Verbose logging | ||
| verbose: false | ||
|
|
||
| # Test mode | ||
| test_mode: false | ||
|
|
||
| # Profiling | ||
| enable_profiling: false | ||
| profile_steps: 100 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,135 @@ | ||||||||||||||||||||||
| #!/usr/bin/env python3 | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| Configuration module for SAMO Emotion Detection System | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| This module provides centralized configuration management for the emotion | ||||||||||||||||||||||
| detection system, ensuring consistency across training and evaluation. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| from typing import Dict, Any | ||||||||||||||||||||||
| from dataclasses import dataclass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Default configuration values | ||||||||||||||||||||||
| DEFAULT_CONFIG = { | ||||||||||||||||||||||
| "model": { | ||||||||||||||||||||||
| "name": "bert-base-uncased", | ||||||||||||||||||||||
| "num_emotions": 28, | ||||||||||||||||||||||
| "hidden_dropout_prob": 0.3, | ||||||||||||||||||||||
| "classifier_dropout_prob": 0.5, | ||||||||||||||||||||||
| "freeze_bert_layers": 6, | ||||||||||||||||||||||
| "temperature": 1.0, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| "training": { | ||||||||||||||||||||||
| "batch_size": 16, | ||||||||||||||||||||||
| "learning_rate": 2e-5, | ||||||||||||||||||||||
| "num_epochs": 10, | ||||||||||||||||||||||
| "weight_decay": 0.01, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| "evaluation": { | ||||||||||||||||||||||
| "threshold": 0.2, # Default evaluation threshold | ||||||||||||||||||||||
| "top_k": 5, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| "prediction": { | ||||||||||||||||||||||
| "threshold": 0.6, # Default prediction threshold | ||||||||||||||||||||||
| "max_length": 512, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_evaluation_threshold() -> float: | ||||||||||||||||||||||
| """Get current evaluation threshold from global config.""" | ||||||||||||||||||||||
| return _config.evaluation_threshold | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_prediction_threshold() -> float: | ||||||||||||||||||||||
| """Get current prediction threshold from global config.""" | ||||||||||||||||||||||
| return _config.prediction_threshold | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @dataclass | ||||||||||||||||||||||
| class EmotionDetectionConfig: | ||||||||||||||||||||||
| """Configuration class for emotion detection system.""" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Model configuration | ||||||||||||||||||||||
| model_name: str = "bert-base-uncased" | ||||||||||||||||||||||
| num_emotions: int = 28 | ||||||||||||||||||||||
| hidden_dropout_prob: float = 0.3 | ||||||||||||||||||||||
| classifier_dropout_prob: float = 0.5 | ||||||||||||||||||||||
| freeze_bert_layers: int = 6 | ||||||||||||||||||||||
| temperature: float = 1.0 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Training configuration | ||||||||||||||||||||||
| batch_size: int = 16 | ||||||||||||||||||||||
| learning_rate: float = 2e-5 | ||||||||||||||||||||||
| num_epochs: int = 10 | ||||||||||||||||||||||
| weight_decay: float = 0.01 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Evaluation configuration | ||||||||||||||||||||||
| evaluation_threshold: float = 0.2 | ||||||||||||||||||||||
| top_k: int = 5 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Prediction configuration | ||||||||||||||||||||||
| prediction_threshold: float = 0.6 | ||||||||||||||||||||||
| max_length: int = 512 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @classmethod | ||||||||||||||||||||||
| def from_dict(cls, config_dict: Dict[str, Any]) -> 'EmotionDetectionConfig': | ||||||||||||||||||||||
| """Create config from dictionary.""" | ||||||||||||||||||||||
| return cls(**config_dict) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def to_dict(self) -> Dict[str, Any]: | ||||||||||||||||||||||
| """Convert config to dictionary.""" | ||||||||||||||||||||||
| return { | ||||||||||||||||||||||
| "model_name": self.model_name, | ||||||||||||||||||||||
| "num_emotions": self.num_emotions, | ||||||||||||||||||||||
| "hidden_dropout_prob": self.hidden_dropout_prob, | ||||||||||||||||||||||
| "classifier_dropout_prob": self.classifier_dropout_prob, | ||||||||||||||||||||||
| "freeze_bert_layers": self.freeze_bert_layers, | ||||||||||||||||||||||
| "temperature": self.temperature, | ||||||||||||||||||||||
| "batch_size": self.batch_size, | ||||||||||||||||||||||
| "learning_rate": self.learning_rate, | ||||||||||||||||||||||
| "num_epochs": self.num_epochs, | ||||||||||||||||||||||
| "weight_decay": self.weight_decay, | ||||||||||||||||||||||
| "evaluation_threshold": self.evaluation_threshold, | ||||||||||||||||||||||
| "top_k": self.top_k, | ||||||||||||||||||||||
| "prediction_threshold": self.prediction_threshold, | ||||||||||||||||||||||
| "max_length": self.max_length, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_default_config() -> EmotionDetectionConfig: | ||||||||||||||||||||||
| """Get default configuration.""" | ||||||||||||||||||||||
| return EmotionDetectionConfig() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_config_from_dict(config_dict: Dict[str, Any]) -> EmotionDetectionConfig: | ||||||||||||||||||||||
| """Get configuration from dictionary with defaults.""" | ||||||||||||||||||||||
| default_config = get_default_config() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Update with provided values | ||||||||||||||||||||||
| for key, value in config_dict.items(): | ||||||||||||||||||||||
| if hasattr(default_config, key): | ||||||||||||||||||||||
| setattr(default_config, key, value) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return default_config | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Global configuration instance | ||||||||||||||||||||||
| _config = get_default_config() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_config() -> EmotionDetectionConfig: | ||||||||||||||||||||||
| """Get current configuration.""" | ||||||||||||||||||||||
| return _config | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def update_config(config_dict: Dict[str, Any]) -> None: | ||||||||||||||||||||||
| """Update global configuration.""" | ||||||||||||||||||||||
| global _config | ||||||||||||||||||||||
| _config = get_config_from_dict(config_dict) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Comment on lines
+126
to
+130
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion update_config discards existing values; perform in-place shallow merge. -def update_config(config_dict: Dict[str, Any]) -> None:
- """Update global configuration."""
- global _config
- _config = get_config_from_dict(config_dict)
+def update_config(config_dict: Dict[str, Any]) -> None:
+ """Update global configuration in place (shallow merge)."""
+ global _config
+ for key, value in config_dict.items():
+ if hasattr(_config, key):
+ setattr(_config, key, value)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def reset_config() -> None: | ||||||||||||||||||||||
| """Reset to default configuration.""" | ||||||||||||||||||||||
| global _config | ||||||||||||||||||||||
| _config = get_default_config() | ||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Config update ignores nested YAML structure; implement nested → flat mapping
Passing a YAML-like dict with sections (model/training/evaluation/prediction) won’t update the dataclass fields. Add flattening so nested keys map to attributes.
Apply this diff:
def get_config_from_dict(config_dict: Dict[str, Any]) -> EmotionDetectionConfig: """Get configuration from dictionary with defaults.""" - default_config = get_default_config() - - # Update with provided values - for key, value in config_dict.items(): - if hasattr(default_config, key): - setattr(default_config, key, value) - - return default_config + cfg = get_default_config() + + # Map nested sections to dataclass fields + section_map = { + "model": { + "name": "model_name", + "num_emotions": "num_emotions", + "hidden_dropout_prob": "hidden_dropout_prob", + "classifier_dropout_prob": "classifier_dropout_prob", + "freeze_bert_layers": "freeze_bert_layers", + "temperature": "temperature", + }, + "training": { + "batch_size": "batch_size", + "learning_rate": "learning_rate", + "num_epochs": "num_epochs", + "weight_decay": "weight_decay", + }, + "evaluation": { + "threshold": "evaluation_threshold", + "top_k": "top_k", + }, + "prediction": { + "threshold": "prediction_threshold", + "max_length": "max_length", + }, + } + + # Apply nested updates + for section, mapping in section_map.items(): + data = config_dict.get(section) + if isinstance(data, dict): + for k, v in data.items(): + attr = mapping.get(k) + if attr and hasattr(cfg, attr): + setattr(cfg, attr, v) + + # Apply any flat overrides + for key, value in config_dict.items(): + if not isinstance(value, dict) and hasattr(cfg, key): + setattr(cfg, key, value) + + return cfg📝 Committable suggestion
🤖 Prompt for AI Agents