You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Wav2Vec 2.0+CNN的语音情感识别模型准确率停滞问题求助

语音情感识别模型准确率停滞问题排查与解决

我尝试用Wav2Vec 2.0结合全连接网络(注:代码中为SimpleNN全连接结构,你提到的CNN可能是笔误)做4类语音情感识别,类别为OAF_Fear、OAF_angry、OAF_happy、OAF_neutral。所有音频已按Wav2Vec 2.0要求完成预处理(截断/填充、重采样),模型定义如下:

import torch
import torch.nn as nn
import torch.optim as optim
from transformers import Wav2Vec2Tokenizer, Wav2Vec2Model

class SimpleNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.fc2 = nn.Linear(hidden_size, output_size)
        self.relu = nn.ReLU()
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.softmax(x)
        return x

tokenizer = Wav2Vec2Tokenizer.from_pretrained("facebook/wav2vec2-base-960h")
model = Wav2Vec2Model.from_pretrained("facebook/wav2vec2-base-960h")

# Modify the last layer to match the number of output classes
label_mapping = {'OAF_Fear': 0, 'OAF_angry': 1, 'OAF_happy': 2, 'OAF_neutral': 3}
num_classes = len(label_mapping)

model.lm_head = nn.Linear(in_features=model.config.hidden_size, out_features=num_classes, bias=True)

for param in model.parameters():
    param.requires_grad = False
for param in model.lm_head.parameters():
    param.requires_grad = True

input_size = 768  # Size of features extracted from pre-trained model
hidden_size = 256
output_size = num_classes  # Number of emotion classes
learning_rate = 0.001
num_epochs = 50
batch_size = 32
root_dir = "/content/drive/MyDrive/BTP_hanan_dataset/Dataset/TESS"

class FullModel(nn.Module):
    def __init__(self, wav2vec_model, simple_nn_model):
        super(FullModel, self).__init__()
        self.wav2vec_model = wav2vec_model
        self.simple_nn_model = simple_nn_model

    def forward(self, x):
        # Get hidden states from pre-trained model
        hidden_states = self.wav2vec_model(x)[0]
        
        # Aggregate hidden states (e.g., by averaging or max-pooling)
        aggregated_hidden_state = torch.mean(hidden_states, dim=1)  # Example: averaging
        
        # Pass through simple neural network
        output = self.simple_nn_model(aggregated_hidden_state)
        
        return output
simple_nn = SimpleNN(input_size, hidden_size, output_size)

for param in simple_nn.parameters():
    param.requires_grad = True

# Combine pre-trained model and simple neural network into a single model
full_model = FullModel(model, simple_nn)

# Loss function and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(full_model.parameters(), lr=learning_rate)

已尝试训练预训练模型的最后一层,并将其输出传入简单全连接网络,但模型准确率始终停滞在35%,更换两个不同数据集后仍无改善,早停机制(patience=5)在7-10轮后触发,请问问题出在哪里?


核心问题排查与修复方案

1. 重复分类头导致的特征冲突

你同时修改了Wav2Vec2的lm_head为分类头,又额外加了SimpleNN做二次分类,属于冗余设计:

  • Wav2Vec2的lm_head参数虽开启梯度,但实际损失只监督SimpleNN的输出,等于白训练了这个头,还会干扰特征传递。
  • 修复:二选一即可——要么删掉修改lm_head的代码,只用SimpleNN做分类;要么去掉SimpleNN,直接用修改后的lm_head输出结果。

2. 特征聚合方式丢失时序信息

语音情感的关键特征(语调起伏、语速变化)都藏在时序维度里,单纯用torch.mean(hidden_states, dim=1)平均会抹平这些信息,导致模型无法捕捉情感差异。

  • 优化方案:
    • 改用多池化拼接:同时保留平均和最大池化结果,提升特征丰富度:
      avg_pool = torch.mean(hidden_states, dim=1)
      max_pool = torch.max(hidden_states, dim=1)[0]
      aggregated = torch.cat([avg_pool, max_pool], dim=1)
      
    • 或者用注意力池化:让模型自动聚焦对情感更重要的时序片段:
      attention_weights = torch.nn.functional.softmax(torch.sum(hidden_states, dim=-1), dim=1).unsqueeze(-1)
      aggregated = torch.sum(hidden_states * attention_weights, dim=1)
      

3. 预训练模型冻结过度

Wav2Vec2是针对语音识别预训练的,和情感识别的特征分布差异很大,完全冻结所有参数会导致提取的特征适配性差。

  • 修复:解冻最后3-5层编码器,让模型微调适配情感任务:
    # 先冻结所有参数
    for param in model.parameters():
        param.requires_grad = False
    # 解冻最后3层编码器
    for layer in model.encoder.layers[-3:]:
        for param in layer.parameters():
            param.requires_grad = True
    

4. 输出层与损失函数冲突

CrossEntropyLoss内部已经包含了Softmax计算,你在SimpleNN末尾再加Softmax会导致数值不稳定,模型收敛困难。

  • 修复:删掉SimpleNN中的self.softmax = nn.Softmax(dim=1)以及forward里的x = self.softmax(x),直接输出fc2的结果。

5. 学习率设置不合理

0.001的学习率对微调预训练模型来说偏大,容易导致震荡;同时训练多个模块时,没有针对性的分层学习率也会影响效果。

  • 优化方案:用分层学习率,预训练解冻层用小学习率,分类头用大学习率:
    optimizer = optim.Adam([
        {'params': model.encoder.layers[-3:].parameters(), 'lr': 1e-5},
        {'params': simple_nn.parameters(), 'lr': 1e-3}
    ])
    

6. 数据集验证环节的潜在问题

换数据集仍无改善,要确认:

  • 类别分布是否均衡?如果某类占比过高,模型会偏向多数类,准确率会卡在略高于随机水平(4类随机是25%)。
  • 验证集划分是否合理?有没有出现训练/验证数据重叠的情况?
  • 预处理是否正确?Wav2Vec2要求输入是原始音频波形,而非梅尔谱,要确认输入维度和格式是否符合要求。

内容的提问来源于stack exchange,提问作者Fathima Hanan Parakkot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 01:55:28