Hubert笔记
基础
- 不同于语言已经是离散化的符号表示,语言是连续的波形
- 大预言模型是自回归模式的,需要一个字一个字的输入,所以想让大预言模型认识语音,就需要将连续的语音表示为离散化的单元。
那么语音中的单元是什么呢?怎么样的单元才是最好的呢?最重要的是学习合适的表示形式。
- 一句话中有许多声音的单元
- 语音中没有统一的词典
- 语音单元没有显示的分割标志
这篇论文给出的解决方案是:自监督的方式,让模型自己学习到语音的离散表示
如果用文本类比的话,我们希望输入的文本就是输出的文本
希望这个模型通过上下文预测出中间三个
A. MFCC(梅尔频率倒谱系数)
- 是什么? MFCC 是一种能够很好地反映人耳听觉特性的音频特征。人耳对低频声音的变化更敏感,对高频声音的变化不那么敏感。MFCC 通过梅尔滤波器组来模拟这一特性。
- 为什么用它? 相比于原始的波形数据,MFCC 更能捕捉声音的“音色”或“质感”信息。例如,不同的人说同一个元音“a”,其音高(基频)可能不同,但他们的 MFCC 特征在整体形状上会非常相似。
- 如何得到? 对一小段音频(例如 20-40 毫秒的一“帧”)进行计算,会得到一个 MFCC 特征向量(通常包含 12-13 个系数)。一段完整的音频(如几秒钟)会被切分成成百上千个这样的帧,因此会得到一个 MFCC 特征向量的序列。
总结:一段音频 → 一个 MFCC 向量序列(一个二维矩阵,行是帧,列是MFCC系数)。
- 梅尔频谱是一个二维图像(时间 vs. 梅尔频率),它保留了非常丰富的信息,包括我们希望用于识别的音色信息,也包含了一些我们想过滤掉的细节(如个体发音的细微差异)。
- MFCC 是对梅尔频谱的进一步压缩和提炼。它通过离散余弦变换(DCT) 这个工具,从每一帧的梅尔频谱中提取出最能代表“声道形状”的倒谱系数。

- 先通过CNN Encoder,先将连续的语音离散化(得到离散的向量)
- 通过BERT结构,也就是双向transformer结构和Mask,学习更好的离散表示(如图遮蔽其中的x2,x3,x4)
计算输出的z2,z3,z4和原来的差距算loss - 网络学习的目标是什么?通过k-mean聚类的MFCC,还有第一轮迭代后的中间表示
算法细节
CNN-Encoder实现
7个1d的卷积层,步长 [5,2,2,2,2,2,2] kernel-size[10,3,3,3,3,2,2]通道数为512
最终的结果是1秒语音有16000个采样点,通过这个encoder之后,转换成50个特征,也就是50个向量,每个帧代表20ms的语音内容。


这里经过了5个卷积层,以第一个卷积层为例,批大小为1,通道数为512,kernel-size为10,步长为5。经过第一个卷积层后由原来的[1,1,16000]变成[1,512,3200]
如何mask?
随机8%的比例选择开始位置,然后把连续的10个输入mask。
网络loss如何计算?
mask位置的loss与非mask位置的loss按一定比例哦混合,即在上图中x1和z1算的就是非mask部分,x2和z2就是mask部分。
计算输出向量与目标向量的余弦相似度
39维MFCC特征是在计算效率、信息完整性和模型性能之间取得的一个经典平衡点。它并非一个绝对的标准,而是一个在语音识别研究中被广泛验证且行之有效的经验值。
MFCC最核心的部分是12维的MFCC系数。这12洗漱捕捉了语音信号的短时功率的网络形状,包络包含了绝大部分与发音内容相关的信息。
原始的12维MFCC是静态特征,只描述了1帧内的频谱特性。但语音是动态的,发音时舌头、嘴唇等器官的运动会导致频谱随时间变化。这种变化率(速度)至关重要。一阶差分就是来描述这种变化的,它计算的是相邻帧之间的MFCC系数的差值。
为了捕捉更精准的信息,比如加速度(变化本身的变化)我们引入二阶差分。二阶差分计算的是一阶差分岁时间的变化。
除了频谱形状,帧与帧之间的能量(响度)变化也是一个非常重要的线索。
因此我们把之前忽略的对数能量,以及它的一阶差分和二阶差分也加入向量特征 12+12+12+3=39维
这39维特征已经能够捕捉到语音信号中与识别内容相关的大部分关键信息。更多的维度(如60维)带来的性能提升很小,但计算成本和存储开销会显著增加。
目标标签如何获得?
wav2vec 2.0
wav2vec是这个方向重要的里程碑,启发了后续很多的模型包括
- hubert
- wavlm
- whisper
核心问题
与LLM一样,能不能对语音进行预训练,得到一个通用的底层表示模型 ,然后只需要在不同下游任务上进行微调就能达到好的性能了。

输入的波形是语音x,然后将cnn输入到cnn,得到z。将z进行量化得到Q,将Z输入到Transformer-encoder进行编码获得C,C与Q对比做loss
Mask是如何做的
随机mask,以p=6.5%的概率选择是否mask,M=10表示如果决定要mask,那么就连续mask姐姐下来连续的10个表示。为什么是这样选择呢?因为这样设置的结果是有一半的语音输入会被mask。
编码器是如何做的?
特征编码器依然采用CNN结构,与HuBERT的特征编码器结构一直,结果就是1秒的语音会输出49个特征表示相当于20ms对应一个语音特征。采样率从16kHZ变成49HZ(也就是原来1秒钟的语音由16000个特征表示,编码后由49个特征表示)
Loss是如何设定的?
对比学习(contrastive learning)是无监督或自监督学习方法,核心思想是通过拉进相似样本的特征表示、推远不相似样本的特征表示,让模型学会从数据中提取有判别性的特征。
针对图1中的灰色方块,要让灰色方块代表的输出与其对应的向量化后的向量(正样本)相似性最高,与其他量化后的向量(负样本)相似性不高。
向量化表示是如何做的?
- 同时存在多个码本,当输入一个原始向量时,从多个码本中找到一个量化后的向量,然后把他们前后拼接在一起,然后经过一个线性的变化,还原成原来的维度,得到量化后的向量。

对比hubert
整体思想和HuBERT类似只是在loss的设计上有不同,采用了量化和对比学习的方式构建了loss ,使得模型可以学习到更好的语音表示。
- 出音频端到端,无需手工特征
- 引入量化模块,把连续表示离散化
- 结合对比学习,提高表示判
- 训练后只需要少量的数据标注,也能微调出好模型。
其实Hubert效果更好,训练更稳定,更强调语义一致性
因为Hubert学习目标是离散的聚类ID,这些ID并不是唯一随机,而是通过k-means聚类获得的,他们包含了隐式的发音、因素、语义等信息。
聚类标签是跨上下文的全局语义锚点,每一个聚类跨多个语音片段出现。
而wav2vec是通过对比学习更强调判别性能。目标是把正样本拉进, 把负样本拉远,但是负样本可能是语义相近的token,这会引入噪声。但哇wav2vec启发了Hubert。
WavLM
之前介绍的wav2vec和hubert都是聚焦在语音识别任务上,并证明了有提升,那在其他语音任务上,也想有一种 统一的语音表示模型。WavLM可以有用于全栈的语音识别任务。
wav2vec和hubert都是通过mask的方式,让预训练模型学习到了关于语音内容的统一表示。那非语音内容等语言信息可以通过什么方式来学习呢。(比如情感,或者说话人信息)
这也是本文的创新点,一个基于降噪的预训练框架。

整体的模型结构和Hubert是一样的,唯一的区别在于对输入数据的构造
- 与Hubert的CNN encoder结构一样
- 仍然采用K-means聚类方法聚类生成伪标签Z序列。
20ms的语音片段

核心的区别是带噪音的片段进行去噪。
WAVLM的训练数据量更多,使用了9W小时语音,Hubert只用了6万小时。