返回模型
说明文档
语音信箱检测器 - 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% - 从不将真人误分类
注意: 该模型经过调优,从不错过真人来电者,这导致一些语音信箱被分类为真人。这对于客服场景是理想的,因为错过真人来电者比偶尔将语音信箱转接给人工客服更糟糕。
优化建议
生产部署
-
使用 ONNX Runtime 优化:
sess_options = ort.SessionOptions() sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL session = ort.InferenceSession("model.onnx", sess_options) -
多路通话的批处理:
# 一次处理多个音频样本 batch_input = np.stack([mel_spec1, mel_spec2, mel_spec3]) # 形状: (3, 1, 128, 251) outputs = session.run(None, {"input": batch_input}) -
复用特征提取: 缓存梅尔滤波器组计算以加快重复处理速度。
许可证
MIT 许可证 - 可免费用于商业和非商业用途。
模型卡片联系方式
如有问题或疑问,请在仓库中提交 issue。
相关模型:
- Wav2Vec2 语音信箱检测器 - 真人检测准确率更高(100%)
- 推荐用于大多数生产场景,因为具有卓越的速度和效率
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