频谱图与梅尔特征


文档摘要

频谱图与梅尔特征 本节摘要:神经网络不擅长直接吃原始波形。它吃频谱图(Spectrogram)更好,吃梅尔频谱图(Mel Spectrogram)最好。2026 年每一条 ASR、TTS、音频分类流水线的生死,几乎都取决于这一个前处理选择。一段 10 秒 16 kHz 的音频是 16 万个浮点数,它们与「狗叫」「单词猫」这类标签几乎完全不相关——信息在,但模型抽不出来。频谱图把人耳忽略的微秒级抖动压扁,保留人耳真正关心的「哪些频率在哪些时刻有能量」;梅尔频谱图更进一步,按人耳的对数感知把频率轴扭曲,使 100→200 Hz 听起来与 1000→2000 Hz 「等距」。本节将从零手写分帧、加窗、STFT、梅尔滤波器组、对数梅尔与 MFCC,讲透每一个生产流水线仍会踩的坑。

频谱图与梅尔特征

本节摘要:神经网络不擅长直接吃原始波形。它吃频谱图(Spectrogram)更好,吃梅尔频谱图(Mel Spectrogram)最好。2026 年每一条 ASR、TTS、音频分类流水线的生死,几乎都取决于这一个前处理选择。一段 10 秒 16 kHz 的音频是 16 万个浮点数,它们与「狗叫」「单词猫」这类标签几乎完全不相关——信息在,但模型抽不出来。频谱图把人耳忽略的微秒级抖动压扁,保留人耳真正关心的「哪些频率在哪些时刻有能量」;梅尔频谱图更进一步,按人耳的对数感知把频率轴扭曲,使 100→200 Hz 听起来与 1000→2000 Hz 「等距」。本节将从零手写分帧、加窗、STFT、梅尔滤波器组、对数梅尔与 MFCC,讲透每一个生产流水线仍会踩的坑。读完本节,你能解释为什么 80 维对数梅尔是 2026 年语音 ML 的事实标准输入。

学习目标

阅读完本节,你应当能够:

  1. 解释频谱图如何把一维波形变成「时间 × 频率」矩阵,并能从零手写分帧、加窗、STFT 流程。
  2. 推导梅尔尺度与赫兹的换算公式,理解为什么人耳对音高的感知是对数的。
  3. 构建梅尔滤波器组,用一个矩阵乘法把 STFT 幅度转成梅尔频谱图。
  4. 计算对数梅尔频谱图MFCC,并说明它们各自的适用场景。
  5. 识别生产环境中的五类典型坑(梅尔数不匹配、采样率上游不匹配、dB 与 log 混淆、归一化漂移、补零泄漏),并给出修复方案。

一、问题与直觉

拿一段 10 秒、16 kHz 的音频。它是 16 万个取值在 [-1, 1] 的浮点数,与标签「狗叫」或「单词 cat」几乎完全不相关。原始波形里确实有信息,但形态让模型难以提取——同一个音素,间隔 100 毫秒说两次,原始样本完全不同。

频谱图修复了这一点。它压扁人耳忽略的时间细节(微秒级抖动),保留人耳真正关心的结构(哪些频率在约 10~25 毫秒的时间窗里有能量)。梅尔频谱图更进一步:人耳对音高的感知是对数的,100 Hz 与 200 Hz 听起来「一样远」,1000 Hz 与 2000 Hz 也「一样远」;梅尔尺度把频率轴扭曲成匹配人耳感知的形态。从 2010 年到 2026 年,梅尔频谱图始终是语音 ML 中最重要的单一特征。

STFT:把波形切成时间-频率矩阵

把波形切成重叠的帧(典型:25 ms 窗、10 ms 步长,在 16 kHz 下即 400 样本 / 160 样本),每帧乘窗函数(默认 Hann,Hamming 略有差异),逐帧 FFT,把幅度谱堆叠成 (n_frames, n_freq_bins) 的矩阵——这就是频谱图。

对数幅度:压缩 5~6 个数量级

原始幅度跨 5~6 个数量级。取 log(|X| + 1e-6)20 * log10(|X|) 压缩动态范围。所有生产流水线都用对数幅度,不用原始幅度。

梅尔尺度:匹配人耳的对数感知

频率 f(赫兹)到梅尔 m 的映射:m = 2595 * log10(1 + f / 700)。1 kHz 以下近似线性,1 kHz 以上近似对数。覆盖 0~8 kHz 的 80 个梅尔箱,是 ASR 的标准输入。

梅尔滤波器组:一次矩阵乘法完成投影

一组在梅尔尺度上等距分布的三角滤波器,每个滤波器是相邻 FFT 箱的加权和。把 STFT 幅度乘以滤波器组矩阵,一次 matmul 即得梅尔频谱图。

对数梅尔频谱图:2026 年的通用前端

log(mel_spec + 1e-10)。Whisper 的输入、Parakeet 的输入、SeamlessM4T 的输入——这是 2026 年事实上的通用音频前端。

MFCC:加一层 DCT

在对数梅尔频谱图上做 II 型离散余弦变换(DCT),保留前 13 个系数。它去相关了特征并进一步压缩。2015 年前是主流,之后被直接吃对数梅尔的 CNN/Transformer 超越;但在说话人识别(x-vectors、ECAPA)中仍在用。

分辨率权衡:窗越长,频率越清,时间越糊

FFT 越大,频率分辨率越好,时间分辨率越差。25 ms / 10 ms 是音频 ML 的默认;音乐用 50 ms / 12.5 ms;瞬态检测(鼓点、爆破音)用 5 ms / 2 ms。

💡 25 ms 不是玄学,而是语音物理的产物:人发音时,口腔形状在约 20~30 ms 内基本稳定,因此 25 ms 的窗近似捕捉到一个「静态」的声道形状。短于 10 ms 抓不到完整的基频周期,长于 50 ms 又把多个音素混在一起。

二、从零实现

第 1 步:分帧

def frame(signal, frame_len, hop): n = 1 + (len(signal) - frame_len) // hop return [signal[i * hop : i * hop + frame_len] for i in range(n)]

10 秒 16 kHz 音频,frame_len=400, hop=160,得到 998 帧。

第 2 步:Hann 窗

import math def hann(N): return [0.5 * (1 - math.cos(2 * math.pi * n / (N - 1))) for n in range(N)]

FFT 前逐元素相乘,消除因非零端点截断造成的频谱泄漏。

第 3 步:STFT 幅度

def stft_magnitude(signal, frame_len=400, hop=160): win = hann(frame_len) frames = frame(signal, frame_len, hop) return [magnitudes(dft([w * s for w, s in zip(win, f)])) for f in frames]

生产代码用 torch.stftlibrosa.stft(FFT 加速、向量化)。这里的循环仅作教学,只在短片段上跑得动。

第 4 步:梅尔滤波器组

def hz_to_mel(f): return 2595.0 * math.log10(1.0 + f / 700.0) def mel_to_hz(m): return 700.0 * (10 ** (m / 2595.0) - 1) def mel_filterbank(n_mels, n_fft, sr, fmin=0, fmax=None): fmax = fmax or sr / 2 mels = [hz_to_mel(fmin) + (hz_to_mel(fmax) - hz_to_mel(fmin)) * i / (n_mels + 1) for i in range(n_mels + 2)] hzs = [mel_to_hz(m) for m in mels] bins = [int(h * n_fft / sr) for h in hzs] fb = [[0.0] * (n_fft // 2 + 1) for _ in range(n_mels)] for m in range(n_mels): for k in range(bins[m], bins[m + 1]): fb[m][k] = (k - bins[m]) / max(1, bins[m + 1] - bins[m]) for k in range(bins[m + 1], bins[m + 2]): fb[m][k] = (bins[m + 2] - k) / max(1, bins[m + 2] - bins[m + 1]) return fb

80 个梅尔箱、覆盖 0~8 kHz、n_fft=400,得到 (80, 201) 的矩阵。把 (n_frames, 201) 的 STFT 幅度乘以它的转置,即得 (n_frames, 80) 的梅尔频谱图。

设计要点:三角滤波器的中心在梅尔尺度上等距,但换算回赫兹后,低频处滤波器很密、高频处很疏——这正是人耳「低频分辨力强、高频分辨力弱」的体现。第 m 个滤波器的左半边是上升斜坡、右半边是下降斜坡,峰值在 bins[m+1]

第 5 步:对数梅尔

def log_mel(mel_spec, eps=1e-10): return [[math.log(max(v, eps)) for v in frame] for frame in mel_spec]

常见替代:librosa.power_to_db(参考值归一化的 dB)、10 * log10(power + eps)。Whisper 用更复杂的裁剪 + 归一化流程(见其 log_mel_spectrogram 函数)。

第 6 步:MFCC

def dct_ii(x, n_coeffs): N = len(x) return [ sum(x[n] * math.cos(math.pi * k * (2 * n + 1) / (2 * N)) for n in range(N)) for k in range(n_coeffs) ]

对每个对数梅尔帧做 DCT,保留前 13 个系数,即得 MFCC 矩阵。第一个系数通常丢弃(它编码了整体能量)。

三、框架对比

2026 年不同任务的特征工程选型:

任务 特征
ASR(Whisper、Parakeet、SeamlessM4T) 80 维对数梅尔,10 ms 步长,25 ms 窗
TTS 声学模型(VITS、F5-TTS、Kokoro) 80 维梅尔,5~12 ms 步长(精细时间控制)
音频分类(AST、PANNs、BEATs) 128 维对数梅尔,10 ms 步长
说话人嵌入(ECAPA-TDNN、WavLM) 80 维对数梅尔,或原始波形 + 自监督
音乐(MusicGen、Stable Audio 2) EnCodec 离散 token(不是梅尔)
关键词唤醒 40 维 MFCC(适配嵌入式小设备)

经验法则:只要不是做音乐,先从 80 维对数梅尔开始。任何偏离都需要举证证明。

# 生产标准:torch 一行搞定对数梅尔 import torchaudio mel = torchaudio.transforms.MelSpectrogram( sample_rate=16000, n_fft=400, hop_length=160, n_mels=80, window_fn=torch.hann_window)(wav) log_mel = torchaudio.transforms.AmplitudeToDB( stype="power", top_db=80)(mel) # 等价于 10*log10(power)

💡 AmplitudeToDBtop_db=80 会把低于峰值 80 dB 的部分截平,起到归一化作用。Whisper 没用 top_db,而是自己一套 clip + 标准化,因此用 HF 的 WhisperProcessor 时不要自己手动算梅尔——直接调它的 get_features,否则数值会与预训练分布不一致。

四、可复用产物

本节产出技能文档(原课程 outputs/skill-feature-extractor.md),针对给定目标模型自动选择特征类型、梅尔数、帧长/步长、归一化方式。核心决策树:

  • 目标是 ASR/分类 → 80(或 128)维对数梅尔,25 ms 窗,10 ms 步。
  • 目标是 TTS → 80 维梅尔,5~12 ms 步长(更细的时间控制)。
  • 目标是关键词唤醒 → 40 维 MFCC(算力受限设备)。
  • 目标是音乐生成 → 用 EnCodec token,不要梅尔。
  • 任何情况下,先固定采样率,再做特征

五、练习

  1. 基础:运行 code/main.py。它合成一段 chirp(频率从 200 Hz 扫到 4000 Hz),逐帧打印 argmax 梅尔箱(可选画图),确认峰值随时间上移与扫频一致。

  2. 进阶:把 n_mels{40, 80, 128}frame_len{200, 400, 800},共九组组合重跑。沿时间轴测量峰值带宽,哪组组合分辨扫频最清楚?解释分辨率权衡。

  3. 挑战:实现 power_to_db,在 AudioMNIST 上用一个小型 CNN 分类器,对比三种特征的 top-1 准确率:(a) 原始对数梅尔;(b) ref=max 的 dB 梅尔;(c) MFCC-13 + 一阶差分 + 二阶差分。报告结果并分析。

本节要点回顾

  1. 神经网络不擅长直接吃原始波形——信息在,但模型抽不出来;频谱图把时间细节压扁,保留人耳关心的频率结构。
  2. STFT = 分帧 + 加窗 + 逐帧 FFT,典型 25 ms 窗 / 10 ms 步,产出 (n_frames, n_freq_bins) 矩阵。
  3. 对数幅度是必做步骤:原始幅度跨 5~6 个数量级,取 log(|X| + eps) 压缩动态范围。
  4. 梅尔尺度 m = 2595·log10(1 + f/700):1 kHz 下近似线性、以上近似对数,匹配人耳感知。
  5. 梅尔滤波器组是梅尔尺度上等距分布的三角滤波器,一次 matmul 把 STFT 投影到梅尔箱。
  6. 对数梅尔是 2026 年通用前端:Whisper、Parakeet、SeamlessM4T 都吃它;非音乐任务先从 80 维对数梅尔开始。
  7. MFCC = 对数梅尔 + DCT,取前 13 个系数,2015 年前是主流,现仍用于说话人识别与嵌入式关键词唤醒。
  8. 五类生产坑:梅尔数不匹配、上游采样率不匹配、dB 与 log 混淆、归一化漂移、补零泄漏——两端都打日志记录特征形状是排查前提。

下一节,我们用这些特征搭建音频分类系统——从 MFCC 上的 k-NN,一路讲到基于对数梅尔的 Transformer 模型 AST 与 BEATs。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U