Downloads · 30 days
0
maryamalikhasi/vemo-speech-emotion-recognition
vemo-speech-emotion-recognition is a machine learning model from maryamalikhasi. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
This repository contains the trained speech emotion recognition model developed for VEMO, an AI-powered voice diary with emotion recognition.
Downloads · 30 days
0
Access
Public
Updated Sep 22, 2026
Repo size
1.3 GB
Likes
0
Public
Click a slice to open those files.
.safetensors1.3 GB · 100%
From the Hugging Face model README
This repository contains the trained speech emotion recognition model developed for VEMO, an AI-powered voice diary with emotion recognition.
The model is designed for Persian speech emotion recognition and predicts four emotion categories:
The final system combines deep speech representations extracted from Wav2Vec2 with a set of acoustic/prosodic features and uses a Logistic Regression classifier for the final emotion prediction.
The final speech emotion recognition pipeline consists of two phases.
Input Audio
│
▼
Wav2Vec2 Feature Extractor
│
▼
Fine-tuned Wav2Vec2 Encoder
│
▼
Temporal Mean Pooling
│
├─────────────── Deep Speech Representation
│
└─────────────── Acoustic / Prosodic Features
│
▼
Feature Concatenation
│
▼
Scaler
│
▼
Logistic Regression
│
▼
Emotion Probabilities
The first phase contains the fine-tuned Wav2Vec2-based speech encoder.
The encoder is based on a Persian speech emotion recognition model built using Wav2Vec2-XLSR and subsequently adapted during the VEMO development process.
The encoder is used to extract a fixed-length deep representation from an input speech signal.
The representation is obtained by applying temporal mean pooling over the Wav2Vec2 hidden states.
The second phase contains the components required for the final classification stage:
The final classifier receives a concatenation of:
The concatenated feature vector is scaled using the stored scaler and passed to the Logistic Regression classifier.
Both Phase 1 and Phase 2 are required for the complete inference pipeline.
vemo-speech-emotion-recognition/
│
├── phase1/
│ ├── config.json
│ ├── model.safetensors
│ ├── preprocessor_config.json
│ └── training_args.bin
│
├── phase2/
│ ├── logistic classifier.joblib
│ ├── scaler.joblib
│ └── metadata.json
│
└── README.md
| File | Description |
|---|---|
config.json | Configuration of the Wav2Vec2 model |
model.safetensors | Trained Wav2Vec2 model weights |
preprocessor_config.json | Audio preprocessing configuration |
training_args.bin | Training configuration metadata |
| File | Description |
|---|---|
logistic classifier.joblib | Trained Logistic Regression classifier |
scaler.joblib | Feature scaler used before classification |
metadata.json | Metadata associated with the final classification pipeline |
The final system predicts four emotion classes:
| Label | Description |
|---|---|
anger | Angry speech |
happiness | Happy speech |
neutral | Neutral speech |
sadness | Sad speech |
For each input audio file, the Wav2Vec2 encoder produces a sequence of hidden representations.
Temporal mean pooling is applied to obtain a fixed-length representation:
Wav2Vec2 hidden states
↓
Temporal mean pooling
↓
Fixed-length speech embedding
The Wav2Vec2 encoder is used as a frozen feature extractor during the final classification stage.
In addition to the deep Wav2Vec2 representation, eight acoustic features are extracted directly from the input speech:
These features are concatenated with the pooled Wav2Vec2 representation before being passed to the feature scaler and Logistic Regression classifier.
The final feature vector is therefore:
Wav2Vec2 representation
+
8 acoustic features
↓
Concatenated feature vector
↓
Feature scaling
↓
Logistic Regression
The model was developed through multiple stages, including evaluation of a pretrained Wav2Vec2 model, audio augmentation, and adaptation using real-world speech data.
The final system uses a frozen Wav2Vec2 encoder combined with acoustic features and a Logistic Regression classifier.
For the complete development process, experiments, and comparison of approaches, see the GitHub repository.
The inference pipeline uses:
torch
transformers
librosa
numpy
joblib
import joblib
import librosa
import numpy as np
import torch
from transformers import Wav2Vec2FeatureExtractor, Wav2Vec2Model
PHASE1_PATH = "path/to/phase1"
PHASE2_PATH = "path/to/phase2"
feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(
PHASE1_PATH
)
encoder = Wav2Vec2Model.from_pretrained(
PHASE1_PATH
)
encoder.eval()
scaler = joblib.load(
f"{PHASE2_PATH}/scaler.joblib"
)
classifier = joblib.load(
f"{PHASE2_PATH}/logistic_classifier.joblib"
)
def extract_acoustic_features(speech, sr):
f0, _, _ = librosa.pyin(
speech,
fmin=librosa.note_to_hz("C2"),
fmax=librosa.note_to_hz("C7"),
sr=sr
)
f0_voiced = f0[~np.isnan(f0)]
if len(f0_voiced) == 0:
f0_mean = 0.0
f0_std = 0.0
f0_range = 0.0
else:
f0_mean = float(np.mean(f0_voiced))
f0_std = float(np.std(f0_voiced))
f0_range = float(
np.max(f0_voiced) - np.min(f0_voiced)
)
rms = librosa.feature.rms(y=speech)[0]
rms_mean = float(np.mean(rms))
rms_std = float(np.std(rms))
zcr_mean = float(
np.mean(
librosa.feature.zero_crossing_rate(speech)[0]
)
)
centroid = librosa.feature.spectral_centroid(
y=speech,
sr=sr
)[0]
centroid_mean = float(np.mean(centroid))
centroid_std = float(np.std(centroid))
return np.array([
f0_mean,
f0_std,
f0_range,
rms_mean,
rms_std,
zcr_mean,
centroid_mean,
centroid_std
])
def predict_emotion(audio_path):
speech, _ = librosa.load(
audio_path,
sr=feature_extractor.sampling_rate,
mono=True
)
with torch.no_grad():
inputs = feature_extractor(
speech,
sampling_rate=feature_extractor.sampling_rate,
return_tensors="pt",
padding=True
)
hidden_states = encoder(
inputs["input_values"]
).last_hidden_state
embedding = (
hidden_states
.mean(dim=1)
.squeeze(0)
.numpy()
)
acoustic_features = extract_acoustic_features(
speech,
feature_extractor.sampling_rate
)
features = np.concatenate(
[embedding, acoustic_features]
).reshape(1, -1)
features_scaled = scaler.transform(features)
probabilities = classifier.predict_proba(
features_scaled
)[0]
return {
emotion: float(probability)
for emotion, probability
in zip(classifier.classes_, probabilities)
}
The paths in the example should be replaced with the local paths to the downloaded phase1 and phase2 directories.
This model is the speech emotion recognition component of VEMO.
The VEMO backend loads:
The backend then processes an input audio file and returns the probability distribution across the four supported emotion classes.
The model was developed and evaluated using a relatively limited amount of real-world speech data.
Important limitations include:
The initial pretrained speech emotion recognition model used in the development process was:
m3hrdadfi/wav2vec2-xlsr-persian-speech-emotion-recognition
The original Persian speech emotion recognition work is based on the ShEMO dataset:
Mohamad Nezami, O., Jamshid Lou, P., & Karami, M. (2019). ShEMO: A large-scale validated database for Persian speech emotion detection. Language Resources and Evaluation, 53(1), 1–16.
VEMO is an AI-powered voice diary with emotion recognition and empathetic response generation.
This repository contains the speech emotion recognition model component developed for VEMO.
For the complete VEMO project, including its overall architecture and other components, see the VEMO GitHub repository.