总结记录一些关于数据增强的探索与发现。
最近花大把时间在调模型,发现在很多花里胡哨的技巧面前,数据增强看似很low,却真的非常有效。
数据增强概述
首先,推荐一篇关于数据增强写得非常不错的博文[https://lilianweng.github.io/posts/2022-04-15-data-gen/], 虽然大部分是都是 cv/nlp 领域的内容,但依然有很多值得借鉴的内容。
数据增强的核心是,对训练数据进行变换,产生新的数据却没有丢失数据本身的特性。
怎样评价数据增强的好坏:Affinity and Diversity,需要留意增强后数据的分布, 以及噪声(增强)数据对模型鲁棒性的影响。
有意思的一点是,有时一些看似并不影响数据分布的增强方法,实际上却影响了。一个例子是论文 Visual Chirality 中讨论的那样,对一张图片进行左右翻转,其实已经改变了图像的分布情况:很多现实中的图片,翻转后是不存在的。 因此可以训练一个分类来判断图片是否进行了左右翻转,进而说明了翻转后图像的数据分布和翻转前有所不同。 另,这篇论文获得了 cvpr2019 的 best paper,虽然实现比较简单,但思路还是很新颖和有趣但。
当然,也并非的增强数据对结果都是正向有效的。
音频领域常见的数据增强
目前,比较推荐的训练方式是 TRSI-Mode(TRaining accept Signal as Input),相比较传统的方案, TRSI 的一个特点就是直接使用原始音频作为输入,所有的数据增强过程都在训练过程内完成。 例如,在 pytorch 的 dataloader 内实现。这样做的显著的好处是可以节省数据落到硬盘的空间,同时,在训练过程中随机进行增强,对增强数据提供了更好的 diversity
当然一个显著的缺点是数据处理速度可能会制约整个训练速度,需要多花些精力在代码层面。
下面介绍几个常用的音频数据增强方法(基于音频采样点信号作为输入)
tempo Vs speed
音频调速应该是大多数语音问题数据增强的首选方案,以 asr 来说,自从 15年 Dan Povey 的论文Audio Augmentation for Speech Recognition之后, 开发成本较低+效果稳定提升,使得 0.9/1.0/1.1 倍速几乎成为了绝大多数 asr 方案的标配。无论 sox 还是 ffmpeg 都有对应脚本很方便的进行调速。
然而,需要注意的一点,无论是 kaldi 还是 speech-brain 中的默认脚本,都使用的是变速且变调的调速方式。 是的,在变速的时候总是会进行变调。例如二倍速看剧,总是会发现说话人的音调变高了。对于 asr 任务中,变调对结果影响不大,但对其他某些任务,例如 vc(voice conversation), 可能我们希望变速的同时,不发生变调。这就是 tempo 变换。
一个例子: 变速后的 cqt 特征,注意观测 tempo 是 speed 后频谱的偏移

在 sox 中,使用参数来区分这两类变换
sox -i input.wav out.wav tempo 1.1 # 变速不变调
sox -i input.wav out.wav speed 1.1 # 变速又变调
事实上,tempo 命令是 speed 命令和 pitch 命令的叠加,变速之后在变调回到输入的音高上,所以性能也会随之慢一点。
另外一个要注意的点是,sox tempo 可以使用 −m|−s|−l 参数来调整细微的参数。 例如 -m for music and -s for speech 详细可参考 sox 文档
pitch
pitch 音高变换也是常用的命令,注意命令参数是使用绝对音高还是相对音高。之前的一些关于 pitch 的经验:
2021-08-02-基于统计方法确定F0提取上下限参数.md
Energy/Volume 变换
音量的变换,很多特征是音量无关的,若并非如此,音量的增强也是有必要的。
Add Noise and RIR
不改变信号长度前提下,对音频信号的加噪声。建议需要通过测试集来选取合适的加噪参数。
针对频谱的数据增强方案
spec Mask
google 提出的一种 mask 方案,对 mel 谱随机某一行/列进行整体 mask,在 asr 领域验证对结果有微小提升。
spec Block Mask
在 Csi 领域里常用的一种 mask 方案,在频谱图中随机 mask 掉某个矩形区域,和 google 的 spec mask 差别不大,最初来源与 视觉中 ReId 任务。可以参考论文 Bag of Tricks and A Strong Baseline for Deep Person Re-identification
spec mean-sub
wenet 里使用的方案,默认每个样本前 n 帧是静音段,从音频频谱中减去前 n 帧的平均值。
代码参考: https://github.com/wenet-e2e/wenet/blob/main/wenet/dataset/processor.py#L446
spec shift
在音乐中常用,特别是使用 cqt/cqt_chrome 特征,频谱层面的平移直接对应音频的 pitch 偏移, 使用起来非常方便
一些实践的经验
实践下来,在 csi(Cover Song Identify) 里,对 spec-shift 和 tempo-changed 这两种增强显著有效。(map10: ~ 0.74 Vs 0.91) Add noise 在某些场景下显著有效。
顺手整理了一套好用的 augmentation 库 😊😊😊