AI Navigate

[P] XGBoost + TF-IDF for emotion prediction — good state accuracy but struggling with intensity (need advice)

Reddit r/MachineLearning / 3/19/2026

💬 OpinionTools & Practical Usage

Key Points

  • The project uses ~1200 samples to predict a 6-class emotional state and an intensity score (1–5), combining TF-IDF text features with engineered metadata and XGBoost models for classification and regression.
  • Emotion classification achieves about 66–67% accuracy, with most confusion between neighboring classes and the dataset described as small and noisy where text features dominate over metadata.
  • Intensity was initially tackled as a classification task with only ~21% accuracy, then switched to regression achieving a MAE of around 1.22 after rounding predictions to 1–5.
  • TF-IDF feature tuning shows a trade-off: reducing features to 500 hurts accuracy, increasing to 1000–1500 yields slight improvements, but the optimal balance remains unclear and feature engineering has had limited impact.

Hey everyone,

I’m working on a small ML project (~1200 samples) where I’m trying to predict:

  1. Emotional state (classification — 6 classes)
  2. Intensity (1–5) of that emotion

The dataset contains:

  • journal_text (short, noisy reflections)
  • metadata like:
    • stress_level
    • energy_level
    • sleep_hours
    • time_of_day
    • previous_day_mood
    • ambience_type
    • face_emotion_hint
    • duration_min
    • reflection_quality

🔧 What I’ve done so far

1. Text processing

Using TF-IDF:

  • max_features = 500 → tried 1000+ as well
  • ngram_range = (1,2)
  • stop_words = 'english'
  • min_df = 2

Resulting shape:

  • ~1200 samples × 500–1500 features

2. Metadata

  • Converted categorical (face_emotion_hint) to numeric
  • Kept others as numerical
  • Handled missing values (NaN left for XGBoost / simple filling)

Also added engineered features:

  • text_length
  • word_count
  • stress_energy = stress_level * energy_level
  • emotion_hint_diff = stress_level - energy_level

Scaled metadata using StandardScaler

Combined with text using:

from scipy.sparse import hstack X_final = hstack([X_text, X_meta_sparse]).tocsr() 

3. Models

Emotional State (Classification)

Using XGBClassifier:

  • accuracy ≈ 66–67%

Classification report looks decent, confusion mostly between neighboring classes.

Intensity (Initially Classification)

  • accuracy ≈ 21% (very poor)

4. Switched Intensity → Regression

Used XGBRegressor:

  • predictions rounded to 1–5

Evaluation:

  • MAE ≈ 1.22

Current Issues

1. Intensity is not improving much

  • Even after feature engineering + tuning
  • MAE stuck around 1.2
  • Small improvements only (~0.05–0.1)

2. TF-IDF tuning confusion

  • Reducing features (500) → accuracy dropped
  • Increasing (1000–1500) → slightly better

Not sure how to find optimal balance

3. Feature engineering impact is small

  • Added multiple features but no major improvement
  • Unsure what kind of features actually help intensity

Observations

  • Dataset is small (1200 rows)
  • Labels are noisy (subjective emotion + intensity)
  • Model confuses nearby classes (expected)
  • Text seems to dominate over metadata

Questions

  1. Are there better approaches for ordinal prediction (instead of plain regression)?
  2. Any ideas for better features specifically for emotional intensity?
  3. Should I try different models (LightGBM, linear models, etc.)?
  4. Any better way to combine text + metadata?

Goal

Not just maximize accuracy — but build something that:

  • handles noisy data
  • generalizes well
  • reflects real-world behavior

Would really appreciate any suggestions or insights 🙏

submitted by /u/Udbhav96
[link] [comments]