ONNX 模型库
返回模型

说明文档

语音信箱检测器 - CNN (ONNX)

快速且轻量级的 CNN 模型,用于实时语音信箱检测。该模型在保持 20 毫秒以下推理时间的同时实现了出色的准确率,非常适合生产环境中的电话系统。

模型描述

  • 模型类型: 音频分类(二元 CNN)
  • 架构: 使用梅尔频谱特征的卷积神经网络
  • 格式: 带外部数据的 ONNX
  • 输入: 16kHz 采样率的 4 秒音频(64,000 个采样点)
  • 输出: 二元分类(真人 vs 语音信箱)
  • 模型大小: 约 13.2 MB

性能指标

准确率

  • 总体准确率: 80.20%(81/101 测试样本)
  • 真人检测: 100.00%(34/34 正确)
  • 语音信箱检测: 70.15%(47/67 正确)
  • 精确率(语音信箱): 100.00%(无假阳性)
  • 召回率(语音信箱): 70.15%
  • F1 分数: 82.46%

推理速度

  • 平均推理时间: 10.82ms(CPU)
  • 最小/最大时间: 10.01ms / 16.00ms
  • 实时能力: 是(< 50ms)

资源效率

  • 模型大小: 18.19 MB(内存中)
  • 推理内存: 约 373 MB
  • 多进程友好: 是(比 Wav2Vec2 高效 67 倍)

与 Wav2Vec2 模型对比

CNN 模型的优势:

  • 速度: 快 65 倍(11ms vs 705ms)
  • 大小: 小 67 倍(18MB vs 1.2GB)
  • 真人检测: 100% 准确率(完美检测)
  • 精确率: 100%(语音信箱检测无假阳性)
  • 部署简单: 无需 transformers 依赖

使用场景

该模型非常适合:

  • 📞 实时电话系统 - 需要即时语音信箱检测
  • 🏭 生产环境 - 具有多个并发工作进程
  • ⚡ 低延迟应用 - 响应时间至关重要
  • 💻 资源受限的部署 - 内存有限
  • 🎯 高精度场景 - 必须避免假阳性(100% 精确率)
  • 👤 真人检测 - 需要完美准确率(真人为 100%)

最适合: 优先考虑速度、可扩展性和语音信箱检测零假阳性的生产系统。

安装

pip install onnxruntime numpy librosa

使用方法

基本推理

import numpy as np
import onnxruntime as ort
import librosa

def extract_mel_spectrogram(audio: np.ndarray, sr: int = 16000) -> np.ndarray:
    """从音频中提取梅尔频谱特征。
    
    Args:
        audio: 形状为 (64000,) 的音频数组 - 16kHz 下的 4 秒音频
        sr: 采样率(默认:16000)
    
    Returns:
        形状为 (1, 1, 128, 251) 的梅尔频谱
    """
    # 计算梅尔频谱
    mel_spec = librosa.feature.melspectrogram(
        y=audio,
        sr=sr,
        n_fft=512,
        hop_length=256,
        n_mels=128,
        fmin=0,
        fmax=8000,
    )
    
    # 转换为对数刻度
    mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)
    
    # 归一化到 [0, 1]
    mel_spec_normalized = (mel_spec_db - mel_spec_db.min()) / (
        mel_spec_db.max() - mel_spec_db.min() + 1e-8
    )
    
    # 重塑为 (1, 1, 128, 251)
    return mel_spec_normalized.reshape(1, 1, 128, -1)

# 加载 ONNX 模型
session = ort.InferenceSession("model.onnx")

# 加载音频(16kHz 下的 4 秒 = 64,000 个采样点)
audio, sr = librosa.load("audio.wav", sr=16000, mono=True)
audio_segment = audio[:64000]

# 如果较短则填充
if len(audio_segment) < 64000:
    audio_segment = np.pad(audio_segment, (0, 64000 - len(audio_segment)))

# 提取特征
mel_spec = extract_mel_spectrogram(audio_segment)

# 运行推理
outputs = session.run(None, {"input": mel_spec.astype(np.float32)})
logits = outputs[0]

# 获取预测结果
prediction_idx = np.argmax(logits, axis=-1)[0]
result = "voicemail" if prediction_idx == 1 else "live_human"

# 获取置信度分数
probabilities = np.exp(logits) / np.sum(np.exp(logits), axis=-1, keepdims=True)
confidence = probabilities[0][prediction_idx]

print(f"Detection: {result} (confidence: {confidence:.2%})")

实时音频处理

import numpy as np
import onnxruntime as ort

class VoicemailDetector:
    """使用 CNN 模型的实时语音信箱检测器。"""
    
    def __init__(self, model_path: str, sample_rate: int = 16000):
        self.session = ort.InferenceSession(model_path)
        self.sample_rate = sample_rate
        self.buffer_duration = 4.0  # 秒
        self.buffer_size = int(sample_rate * self.buffer_duration)
        self.audio_buffer = np.zeros(self.buffer_size, dtype=np.float32)
    
    def add_audio(self, audio_chunk: np.ndarray):
        """添加音频块到缓冲区(滑动窗口)。"""
        chunk_size = len(audio_chunk)
        
        # 移动缓冲区并添加新音频
        self.audio_buffer = np.roll(self.audio_buffer, -chunk_size)
        self.audio_buffer[-chunk_size:] = audio_chunk
    
    def detect(self) -> tuple[str, float]:
        """从当前缓冲区检测语音信箱。
        
        Returns:
            返回 (预测结果, 置信度) 元组
        """
        # 提取特征
        mel_spec = extract_mel_spectrogram(self.audio_buffer, self.sample_rate)
        
        # 运行推理
        outputs = self.session.run(None, {"input": mel_spec})
        logits = outputs[0]
        
        # 获取预测结果
        prediction_idx = np.argmax(logits, axis=-1)[0]
        result = "voicemail" if prediction_idx == 1 else "live_human"
        
        # 计算置信度
        probabilities = np.exp(logits) / np.sum(np.exp(logits), axis=-1, keepdims=True)
        confidence = probabilities[0][prediction_idx]
        
        return result, float(confidence)

# 使用示例
detector = VoicemailDetector("model.onnx")

# 模拟流式音频
for audio_chunk in audio_stream:
    detector.add_audio(audio_chunk)
    result, confidence = detector.detect()
    print(f"{result}: {confidence:.2%}")

模型架构

输入: 音频 (4秒 @ 16kHz) → 梅尔频谱 (128 梅尔, 251 时间步)
  ↓
Conv2D (32 滤波器, 3x3) + ReLU + MaxPool2D
  ↓
Conv2D (64 滤波器, 3x3) + ReLU + MaxPool2D
  ↓
Conv2D (128 滤波器, 3x3) + ReLU + MaxPool2D
  ↓
Flatten + Dropout (0.5)
  ↓
Dense (128) + ReLU + Dropout (0.5)
  ↓
Dense (2) → Softmax
  ↓
输出: [真人概率, 语音信箱概率]

重要实现说明

音频要求

  • 时长: 精确的 4 秒(64,000 个采样点)
  • 采样率: 16kHz
  • 声道: 单声道
  • 格式: Float32 numpy 数组

特征提取

模型期望具有以下参数的梅尔频谱:

  • n_fft: 512
  • hop_length: 256
  • n_mels: 128
  • fmin: 0 Hz
  • fmax: 8000 Hz
  • 归一化: 对数刻度转换后进行最小-最大缩放到 [0, 1]

模型输入/输出

输入:

  • 名称:input
  • 形状:[1, 1, 128, 251]
  • 类型:float32
  • 格式:归一化的梅尔频谱

输出:

  • 名称:output
  • 形状:[1, 2]
  • 类型:float32
  • 类别:[0: 真人, 1: 语音信箱]

训练详情

  • 架构: 用于音频分类的自定义 CNN
  • 训练数据: 精选的语音信箱问候语和真人回复数据集
  • 优化重点: 语音信箱提示音和静音检测
  • 导出方法: PyTorch → ONNX

优缺点

优点 ✅

  • 完美的真人检测(100% 准确率 - 从不错过真人)
  • 完美的语音信箱精确率(100% - 零假阳性)
  • 非常快的推理速度(11ms - 比替代方案快 65 倍)
  • 极小的内存占用(18MB - 比替代方案小 67 倍)
  • 简单的预处理(只需梅尔频谱,无需 transformers)
  • 生产系统实时可用
  • 多进程友好
  • 出色的 F1 分数(82.46%)显示均衡的性能

缺点 ❌

  • 语音信箱检测召回率较低(70.15% - 会漏掉一些语音信箱)
  • 可能将一些语音信箱分类为真人(30% 假阴性)
  • 不如基于 transformer 的模型复杂
  • 权衡:优先保证不错过真人,而非捕获所有语音信箱

评估结果

完整测试数据集(101 个样本)

类别 正确 总数 准确率
真人 34 34 100.0%
语音信箱 47 67 70.15%
总计 81 101 80.20%

混淆矩阵

预测为真人 预测为语音信箱
实际真人 34(真阴性) 0(假阳性)
实际语音信箱 20(假阴性) 47(真阳性)

关键指标摘要

  • 精确率(语音信箱): 100.00% - 当它说是语音信箱时,总是正确的
  • 召回率(语音信箱): 70.15% - 捕获 70% 的所有语音信箱
  • F1 分数: 82.46% - 精确率和召回率的调和平均数
  • 真人准确率: 100.00% - 从不将真人误分类

注意: 该模型经过调优,从不错过真人来电者,这导致一些语音信箱被分类为真人。这对于客服场景是理想的,因为错过真人来电者比偶尔将语音信箱转接给人工客服更糟糕。

优化建议

生产部署

  1. 使用 ONNX Runtime 优化:

    sess_options = ort.SessionOptions()
    sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
    session = ort.InferenceSession("model.onnx", sess_options)
    
  2. 多路通话的批处理:

    # 一次处理多个音频样本
    batch_input = np.stack([mel_spec1, mel_spec2, mel_spec3])  # 形状: (3, 1, 128, 251)
    outputs = session.run(None, {"input": batch_input})
    
  3. 复用特征提取: 缓存梅尔滤波器组计算以加快重复处理速度。

许可证

MIT 许可证 - 可免费用于商业和非商业用途。

模型卡片联系方式

如有问题或疑问,请在仓库中提交 issue。


相关模型:

bdatdo0601/voicemail-detector-cnn-onnx

作者 bdatdo0601

↓ 1 ♥ 1

创建时间: 2025-10-26 23:38:11+00:00

更新时间: 2025-11-13 22:30:04+00:00

在 Hugging Face 上查看

文件 (15)

.gitattributes
.gitignore
MODEL_CARD.md
README.md
TRAINING_GUIDE.md
config.json
example.py
model.onnx ONNX
model.onnx.data
pyproject.toml
rename_onnx_files.py
requirements.txt
train_standalone.py
uv.lock
validate_onnx.py