Acoustic Emotion Recognition

Predicting a speaker's emotion from the acoustic signature of their voice — five classifiers benchmarked in scikit-learn and cross-validated against WEKA.

Timeline

2026

Status

Open-source

Overview

A supervised-learning project that predicts a speaker's emotional state from the acoustic signal of their voice (pitch, speech rate, jitter, shimmer and MFCC coefficients) across 10 emotion classes. Five classifiers are implemented in Python with scikit-learn, then the entire validation is reproduced in WEKA to confirm the results hold across tools rather than just across folds.

A full walk-through of the decisions and surprises is in the build-log; the theory underneath the models lives in my logistic regression and linear regression posts.

The problem

The Acoustic Emotion Vocal Signature dataset is 10,000 balanced voice samples labelled with one of 10 emotions. The constraints I set:

  • Recognise emotion from the acoustic signal, not from textual shortcuts — so any content-derived feature that leaks the answer is off the table.
  • Validate honestly. No data leakage in preprocessing, and every result confirmed against a second, independent implementation (WEKA) before trusting it.

Approach

The pipeline is a single, leak-free flow applied identically to every model:

  • Feature engineering: parse the stringified MFCC array into 13 numeric columns, encode categorical metadata, and drop non-predictive columns (speaker ID, language) plus the near-leakage sentiment score;
  • Feature selection: score features by mutual information on the training set only, keeping the three that carry real signal (pitch, speech rate, speech duration) and discarding 17 noisy ones that were dragging down distance-based models;
  • Modelling: a stratified 80/20 holdout, then StandardScaler and the classifier inside one imblearn pipeline so scaling never sees the test data.

Five classifiers from the supervised shortlist are compared: logistic regression, naïve Bayes, KNN, decision tree, and a single-hidden-layer MLP, scored on accuracy, weighted F1, and weighted ROC AUC.

Validation: scikit-learn vs WEKA

The same protocol (80/20 holdout, standardized features, same selected columns) runs in WEKA through FilteredClassifier, so the scaler is fit on the training split only, mirroring the scikit-learn pipeline. Logistic regression and naïve Bayes matched almost exactly across both tools. KNN and the decision tree diverged; WEKA's J48 (C4.5) is a different tree from scikit-learn's CART, and the comparison surfaced an unnecessary resampling step that was quietly penalising KNN on already-balanced data. The MLP was the strongest scikit-learn model, with a ROC AUC of 0.978.

The point of the exercise: a notebook that looks internally consistent can still hide a questionable choice. A second implementation is what reveals it.

What's next

This is the classification leg of a broader machine-learning project that also tackles regression and unsupervised learning (clustering / PCA), each validated the same way (scikit-learn against WEKA). Both are in progress and will get their own write-ups.

Tech stack

Python · scikit-learn · imbalanced-learn · pandas · NumPy · Matplotlib / Seaborn · WEKA · Jupyter.

Curious how this was built?

I write about the backend×AI wedge — wins and failures included. Follow along, or say hi.