ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【超详细】CREPE 与 SPICE:深度学习基频检测的原理、架构与实践

2026/8/17 19:40:12 拓冰建站 浏览量
【超详细】CREPE 与 SPICE:深度学习基频检测的原理、架构与实践 文章目录1. 从传统方法到深度学习基频检测的范式转换1.1 传统方法的共同瓶颈1.2 CREPE Convolutional Representation for Pitch Estimation1.3 SPICE Spectral Pitch Estimation2. CREPE 的数学框架与网络架构2.1 把基频检测变成分类问题2.2 网络结构六层一维卷积2.3 从概率分布到基频估计3. 训练策略与数据增强3.1 数据集3.2 数据增强提升鲁棒性3.3 损失函数的标签软化4. SPICE面向移动端的轻量化4.1 与 CREPE 的架构对比4.2 SPICE 的速度优势5. 使用 TensorFlow Hub 快速部署5.1 加载预训练模型5.2 完整的本地实现简化版5.3 推理示例6. CREPE 与 SPICE 的工程对比与选型建议6.1 性能对比6.2 选择建议6.3 工程中的注意事项7. 从 CREPE 到更强大的通用音频模型1. 从传统方法到深度学习基频检测的范式转换1.1 传统方法的共同瓶颈HPS、倒谱、SWIPE、YIN 这些算法共享一个基本假设基频可以通过分析单帧信号的频谱或自相关结构来确定。它们的差异在于如何构建特征和搜索峰值但底层逻辑相同。这些方法的工程局限已经在前几篇中反复出现对噪声敏感、对时变信号乏力、对波形畸变脆弱。根本原因在于手工设计的特征和匹配规则无法覆盖真实音频的多样性。深度学习提供了一条不同的路径让模型从大量标注数据中自动学习从频谱到基频的映射关系。输入是原始音频或其频谱表示输出是基频估计值或概率分布。模型通过反向传播自动调整参数不需要手动设计任何特征提取规则。1.2 CREPE Convolutional Representation for Pitch EstimationCREPE 由 Kim 等人于 2018 年发表是第一个基于卷积神经网络的单音基频检测模型在标准数据集上达到了当时的最优性能。CREPE 的贡献在于证明了深度卷积网络可以直接从原始波形中学习基频将基频检测建模为分类问题而非回归问题输出基频的概率分布在噪声和混响条件下展现了远超传统方法的鲁棒性1.3 SPICE Spectral Pitch EstimationSPICE是 Google 在 2019 年提出的轻量级基频检测模型与 CREPE 的思路类似但架构更轻适合在移动设备上部署。目标是在保持较高精度的同时大幅降低计算量使实时基频检测在手机上成为可能。2. CREPE 的数学框架与网络架构2.1 把基频检测变成分类问题CREPE 将连续的基频值离散化为360 个类别覆盖从 C1约 32.7 Hz到 C7约 2093 Hz的范围每个类别对应一个音分cent的间隔。模型的任务是给定一帧音频输出一个 360 维的概率向量每一维表示对应基频是正确值的概率。对于真值基频f 0 t r u e f_0^{true}f0true​模型输出概率分布p ( c ∣ x ) p(c | x)p(c∣x)其中c ∈ { 1 , 2 , . . . , 360 } c \in \{1, 2, ..., 360\}c∈{1,2,...,360}是基频类别索引。训练使用交叉熵损失L − ∑ c y c log ⁡ p ( c ∣ x ) L -\sum_{c} y_c \log p(c | x)L−c∑​yc​logp(c∣x)其中y c y_cyc​是标签分布通常是围绕真值的单峰高斯分布而不是 one-hot 硬标签这样可以为附近类别赋予部分概率软化训练目标。硬标签在分类边界清晰时没问题比如猫和狗但基频检测有一个特殊性基频是一个连续量人为切成 360 个离散类别必然引入边界误差。举个例子假设类别 119 对应 200.0 Hz类别 120 对应 201.0 Hz类别 121 对应 202.0Hz。如果真实基频是 200.6 Hz它离类别 120 更近差 0.4 Hz离类别 119 差 0.6Hz。硬标签会强行要求模型输出类别 120 的概率为 1完全忽略真实值其实在 119 和 120 之间这个事实。更严重的问题硬标签让模型在训练时对自己的错误判断过于自信。当模型预测类别 119 时损失函数会施加最大的惩罚即使 119 和 120在频率上只差 1 Hz听觉上几乎没有区别。这种过度惩罚会让模型学会输出非常尖锐的概率分布反而在推理时失去了平滑性。2.2 网络结构六层一维卷积CREPE 的输入是原始波形的一帧长度 1024 个采样点在 16 kHz 采样率下约 64 ms。网络结构如下层类型卷积核数核大小步长输出维度1Conv1D10245124256×1282Conv1D128641256×1283Conv1D128641256×1284Conv1D128641256×1285Conv1D256641256×2566Conv1D512641256×512最后接全局平均池化将每个通道的特征压缩为一个标量得到 512 维向量再经过一个全连接层输出 360 维的概率分布。设计思想第一层的大卷积核512相当于在时域上提取宽带特征覆盖约 32 ms 的波形能捕捉多个基频周期步长 4 的下采样降低时间分辨率减少计算量中间层的小卷积核64逐层提取更高层的抽象特征全局平均池化将时序特征压缩为固定维度使网络对时间偏移不敏感2.3 从概率分布到基频估计在推理阶段给定概率分布p ( c ∣ x ) p(c|x)p(c∣x)基频估计为f ^ 0 ∑ c p ( c ∣ x ) ⋅ f c \hat{f}_0 \sum_{c} p(c|x) \cdot f_cf^​0​c∑​p(c∣x)⋅fc​即加权平均其中f c f_cfc​是类别c cc对应的基频值音分尺度下线性插值。这种软估计比直接取 argmax 更平滑减少了离散化带来的量化误差。3. 训练策略与数据增强3.1 数据集CREPE 使用了多个公开数据集进行训练和验证RWC Music Database包含乐器独奏录音基频标注精度高Medley-solos-DB多乐器独奏数据集MIR-1K人声清唱数据集Bach10小提琴等乐器的多声部录音训练集总时长约 16 小时覆盖人声和多种乐器的稳态与动态音高变化。3.2 数据增强提升鲁棒性CREPE 训练时使用了两种增强策略添加噪声在干净音频中混入不同信噪比的白噪声使模型学习在噪声条件下提取基频。添加混响通过卷积混响脉冲响应模拟不同声学环境下的录音提升模型对房间反射的鲁棒性。这两种增强使得 CREPE 在真实录音条件下有噪声、有混响的表现远优于在理想实验室条件下训练的传统方法。3.3 损失函数的标签软化直接使用 one-hot 硬标签会让模型在真实基频附近过于自信而且离散化带来的边界效应会降低估计精度。CREPE 使用高斯核软化标签y c exp ⁡ ( − ( c − c t r u e ) 2 2 σ 2 ) y_c \exp\left(-\frac{(c - c_{true})^2}{2\sigma^2}\right)yc​exp(−2σ2(c−ctrue​)2​)其中σ \sigmaσ通常取 25 音分0.25 半音。这样模型学到的不是精确的某个类别而是围绕真值的一个分布推理时加权平均能得到更精细的估计。4. SPICE面向移动端的轻量化4.1 与 CREPE 的架构对比SPICE 同样将基频检测建模为分类问题输出基频的概率分布。但它在设计上做了多项轻量化修改输入更短1024 采样点CREPE 相同卷积核数更少最大 256 通道CREPE 最大 512使用深度可分离卷积将标准卷积分解为逐通道卷积 逐点卷积参数量减少约 8 倍全连接层更小输出维度相同但中间特征维度从 512 降到 256总体参数量从 CREPE 的约 2200 万降到约 300 万在手机 CPU 上可以实现实时推理。4.2 SPICE 的速度优势CREPE 在 GPU 上运行速度很快但在 CPU 上每帧推理约需 5-10 ms难以满足实时要求。SPICE 通过结构优化和量化在移动 CPU 上每帧推理时间约 1-3 ms可以在 Android/iOS 设备上以 30 fps 以上的帧率运行。5. 使用 TensorFlow Hub 快速部署5.1 加载预训练模型Google 在 TensorFlow Hub 上发布了 CREPE 和 SPICE 的预训练模型可以直接加载使用importtensorflow_hubashubimportnumpyasnp# 加载 CREPE 模型crepe_modelhub.load(https://tfhub.dev/google/spice/2)# SPICE# crepe_model hub.load(https://tfhub.dev/google/crepe/1) # CREPE# 加载音频defload_audio(file_path,sample_rate16000):加载音频并重采样到 16 kHzimportlibrosa audio,srlibrosa.load(file_path,srsample_rate,monoTrue)returnaudio audioload_audio(test_audio.wav)# 模型期望输入float32 数组形状 [batch, time]# 推理outputcrepe_model(audio[np.newaxis,:].astype(np.float32))# 输出是基频概率分布形状 [batch, time_frames, n_pitch_classes]# 转换为基频值f0_probsoutput.numpy().squeeze()# 音分到频率的转换# 模型类别对应从 0 到 7180 音分约 32.7 Hz 到 2093 Hzcentsnp.arange(f0_probs.shape[-1])# 0-7180freqs10*2**(cents/1200)# 将音分转换为 Hz# 加权平均得到基频f0_estimatednp.sum(f0_probs*freqs,axis-1)/(np.sum(f0_probs,axis-1)1e-8)5.2 完整的本地实现简化版不依赖 TensorFlow Hub 的纯 PyTorch 实现结构参考 CREPEimporttorchimporttorch.nnasnnimportnumpyasnpclassCREPEModel(nn.Module): CREPE 风格的一维卷积基频检测网络 def__init__(self,n_pitch_classes360,sample_rate16000):super().__init__()self.sample_ratesample_rate self.n_pitch_classesn_pitch_classes# 六层卷积self.conv1nn.Conv1d(1,1024,kernel_size512,stride4,padding254)self.conv2nn.Conv1d(1024,128,kernel_size64,stride1,padding31)self.conv3nn.Conv1d(128,128,kernel_size64,stride1,padding31)self.conv4nn.Conv1d(128,128,kernel_size64,stride1,padding31)self.conv5nn.Conv1d(128,256,kernel_size64,stride1,padding31)self.conv6nn.Conv1d(256,512,kernel_size64,stride1,padding31)# 全局平均池化 全连接self.fcnn.Linear(512,n_pitch_classes)self.relunn.ReLU()self.dropoutnn.Dropout(0.2)defforward(self,x):# x: [batch, 1, time]xself.relu(self.conv1(x))xself.dropout(x)xself.relu(self.conv2(x))xself.dropout(x)xself.relu(self.conv3(x))xself.dropout(x)xself.relu(self.conv4(x))xself.dropout(x)xself.relu(self.conv5(x))xself.dropout(x)xself.relu(self.conv6(x))# 全局平均池化xx.mean(dim-1)# [batch, 512]# 全连接输出概率xself.fc(x)xtorch.softmax(x,dim-1)returnxdefestimate_f0(self,audio_frame): audio_frame: numpy 数组 [1024]16 kHz 采样 返回: 基频估计值 (Hz) self.eval()withtorch.no_grad():xtorch.FloatTensor(audio_frame).unsqueeze(0).unsqueeze(0)probsself.forward(x).squeeze().numpy()# 音分到频率转换centsnp.arange(self.n_pitch_classes)# 0-359# 假设类别从 C1 (32.7 Hz) 开始每个类别间隔 10 音分base_freq32.7freqsbase_freq*2**(cents*10/1200)f0np.sum(probs*freqs)/(np.sum(probs)1e-8)returnf05.3 推理示例# 创建模型随机初始化仅供结构演示modelCREPEModel(n_pitch_classes360)# 生成测试信号440 Hz 正弦波sample_rate16000f0_true440.0tnp.linspace(0,1024/sample_rate,1024,endpointFalse)audionp.sin(2*np.pi*f0_true*t)*0.5# 估计基频f0_estmodel.estimate_f0(audio)print(f真实基频:{f0_true:.2f}Hz)print(f模型估计:{f0_est:.2f}Hz)注意随机初始化的模型无法产生有意义的输出实际使用时需要加载预训练权重。TensorFlow Hub 上的模型是训练好的推荐直接使用。6. CREPE 与 SPICE 的工程对比与选型建议6.1 性能对比指标CREPESPICE参数量~2200 万~300 万每帧推理时间CPU5-10 ms1-3 ms每帧推理时间GPU1 ms0.5 ms噪声鲁棒性SNR10dB优良混响鲁棒性优良频率估计精度稳态±5 音分±10 音分适合部署平台服务器/工作站移动端/嵌入式6.2 选择建议选择 CREPE 的场景离线批量处理对精度要求很高有 GPU 资源可用处理包含复杂噪声和混响的真实录音音乐信息检索研究、音频分析工具开发选择 SPICE 的场景实时音高检测如乐器调音器 App、实时可视化移动端或嵌入式设备对延迟敏感但对精度要求略低的场景需要在浏览器中运行的 Web 应用6.3 工程中的注意事项帧长与时间分辨率两个模型都使用 1024 采样点的输入帧64 ms 16 kHz。如果需要更高的时间分辨率可以减小帧移hop size但会增加计算量。音高范围限制CREPE 和 SPICE 的检测范围大约在 32.7 Hz 到 2093 Hz 之间。低于或高于此范围的信号如低音贝斯、短笛极高音无法被正确检测。多音高混合两个模型都是单音基频检测模型无法处理同时存在的多个音高如和弦。如果需要多音高检测需要使用专门的模型如 DeepSalience、MT3 等。采样率适配模型在 16 kHz 采样率下训练输入音频必须重采样到 16 kHz。使用 librosa 的load(sr16000)可以一步完成重采样和单声道转换。7. 从 CREPE 到更强大的通用音频模型CREPE 和 SPICE 开创了深度学习基频检测的先河之后的发展方向包括多音高检测同时检测多个同时发声的音高如 MT3多任务音乐转录 Transformer音高 其他属性的联合估计如同时输出基频、清浊音概率、音量包络端到端的音乐转录直接从波形到乐谱级别的输出自监督预训练使用大规模无标注音频学习通用音频表征再微调到基频检测任务如果你需要在复杂真实场景中进行基频检测优先使用 CREPE 或 SPICE 的预训练模型而不是重新训练。训练一个可比拟的精度的模型需要大量的标注数据和计算资源工程成本远高于直接调用预训练权重。深度学习基频检测的优势在于从数据中自动学习鲁棒特征使模型在噪声、混响、时变条件下依然保持稳定输出。你在实际项目中用过 CREPE 或 SPICE 吗遇到了哪些传统方法无法解决的场景欢迎交流。