Google 的 WebRTC VAD 算法(特别是 "aggressiveness")
Google's WebRTC VAD algorithm (esp. "aggressiveness")
我知道Google的WebRTC VAD算法使用高斯混合模型(GMM),但我的数学知识薄弱,所以我不太明白那是什么意思。说它是一种基于统计的机器学习模型是否正确?对于 VAD,经过训练可以识别语音与噪声的模型是否正确?
我正在写一篇论文,我创建了一个脚本,该脚本利用 API 来区分声音和噪音。它有效,但我需要在我的论文中从最基本的层面解释它用来做出决定的机制。
最紧迫的是,我需要在某种程度上了解 "aggressiveness" 设置对算法的作用。它真的只是规定了一个置信度阈值吗?它有任何声学反响吗?
更新:
我的超基本理解是:google 可能在一堆预先标记的 "noise" 和 "speech" 上训练了他们的模型并存储了每个的特征;然后它采用未知样本并查看它是否更像噪声数据或语音数据。我不知道测量的特征是什么,但我假设至少测量了音高和振幅。
它使用 GMM 来计算它属于一个总体或另一个总体的概率。
攻击性可能设置了它用于做出决定的阈值,但我不完全知道这部分是如何工作的。
相关代码在这里:https://chromium.googlesource.com/external/webrtc/+/refs/heads/master/common_audio/vad/vad_core.c
"aggressiveness" 设置决定了以下常量(我展示模式 0 和 3 以供比较):
// Constants used in WebRtcVad_set_mode_core().
//
// Thresholds for different frame lengths (10 ms, 20 ms and 30 ms).
//
// Mode 0, Quality.
static const int16_t kOverHangMax1Q[3] = { 8, 4, 3 };
static const int16_t kOverHangMax2Q[3] = { 14, 7, 5 };
static const int16_t kLocalThresholdQ[3] = { 24, 21, 24 };
static const int16_t kGlobalThresholdQ[3] = { 57, 48, 57 };
// Mode 3, Very aggressive.
static const int16_t kOverHangMax1VAG[3] = { 6, 3, 2 };
static const int16_t kOverHangMax2VAG[3] = { 9, 5, 3 };
static const int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };
static const int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 };
我不太明白悬垂和 local/global 阈值是如何发挥作用的。这些是严格的统计参数吗?
跟踪代码,您会看到上面列出的预设 4 个值,这些值根据“攻击性”而变化:kOverHangMax{1,2}*, kLocalThreshold*, kGlobalThreshold*
这些映射到这些4 个内部数组(按攻击性索引):
self->over_hang_max_1[], self->over_hang_max_2[], self->individual[], self->total[]
进一步查看 vad_core.c
中的第 158 行,我们发现根据帧长度使用了不同的值。 frame_length
是待分析音频的"atom"或"chunk":
// Set various thresholds based on frame lengths (80, 160 or 240 samples).
if (frame_length == 80) {
overhead1 = self->over_hang_max_1[0];
overhead2 = self->over_hang_max_2[0];
individualTest = self->individual[0];
totalTest = self->total[0];
} else if (frame_length == 160) {
overhead1 = self->over_hang_max_1[1];
overhead2 = self->over_hang_max_2[1];
individualTest = self->individual[1];
totalTest = self->total[1];
} else {
overhead1 = self->over_hang_max_1[2];
overhead2 = self->over_hang_max_2[2];
individualTest = self->individual[2];
totalTest = self->total[2];
}
直觉
因此,音频块(240 个样本)越大,算法越 "aggressive",而较小的 80 个样本帧是 "less aggressive":但这是为什么呢?直觉是什么?
calling-code(使用 vad_core
)为其提供 frames_length
音频块。因此,如果您正在使用 VAD 的音频文件有 10 分钟长,那么在该音频上滑动 window 将生成 frame_length
块并将其传递给此代码。
使用 8000Hz 采样率的音频 运行,当 frame_length
较小 (80) 时,分辨率 (10ms) 是细粒度的,VAD 信号将非常精确。将准确跟踪变化,VAD 估计将为 "reasonable" ... 当 frame_length
较大 (240) 时,分辨率更高 "coarse",并且 VAD 信号将更少调整信号语音的微小(<30 毫秒)变化-activity ... 因此 "less cautious"。
因此,我宁愿谈论 "cautiously" 或 "assertively" 它如何跟踪它正在估计的基础语音信号,而不是咄咄逼人。
我希望这有助于推断它在做什么。至于值本身,它们只是由于不同大小的音频帧而变化的算法细节。
我知道Google的WebRTC VAD算法使用高斯混合模型(GMM),但我的数学知识薄弱,所以我不太明白那是什么意思。说它是一种基于统计的机器学习模型是否正确?对于 VAD,经过训练可以识别语音与噪声的模型是否正确?
我正在写一篇论文,我创建了一个脚本,该脚本利用 API 来区分声音和噪音。它有效,但我需要在我的论文中从最基本的层面解释它用来做出决定的机制。
最紧迫的是,我需要在某种程度上了解 "aggressiveness" 设置对算法的作用。它真的只是规定了一个置信度阈值吗?它有任何声学反响吗?
更新:
我的超基本理解是:google 可能在一堆预先标记的 "noise" 和 "speech" 上训练了他们的模型并存储了每个的特征;然后它采用未知样本并查看它是否更像噪声数据或语音数据。我不知道测量的特征是什么,但我假设至少测量了音高和振幅。
它使用 GMM 来计算它属于一个总体或另一个总体的概率。
攻击性可能设置了它用于做出决定的阈值,但我不完全知道这部分是如何工作的。
相关代码在这里:https://chromium.googlesource.com/external/webrtc/+/refs/heads/master/common_audio/vad/vad_core.c
"aggressiveness" 设置决定了以下常量(我展示模式 0 和 3 以供比较):
// Constants used in WebRtcVad_set_mode_core().
//
// Thresholds for different frame lengths (10 ms, 20 ms and 30 ms).
//
// Mode 0, Quality.
static const int16_t kOverHangMax1Q[3] = { 8, 4, 3 };
static const int16_t kOverHangMax2Q[3] = { 14, 7, 5 };
static const int16_t kLocalThresholdQ[3] = { 24, 21, 24 };
static const int16_t kGlobalThresholdQ[3] = { 57, 48, 57 };
// Mode 3, Very aggressive.
static const int16_t kOverHangMax1VAG[3] = { 6, 3, 2 };
static const int16_t kOverHangMax2VAG[3] = { 9, 5, 3 };
static const int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };
static const int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 };
我不太明白悬垂和 local/global 阈值是如何发挥作用的。这些是严格的统计参数吗?
跟踪代码,您会看到上面列出的预设 4 个值,这些值根据“攻击性”而变化:kOverHangMax{1,2}*, kLocalThreshold*, kGlobalThreshold*
这些映射到这些4 个内部数组(按攻击性索引):
self->over_hang_max_1[], self->over_hang_max_2[], self->individual[], self->total[]
进一步查看 vad_core.c
中的第 158 行,我们发现根据帧长度使用了不同的值。 frame_length
是待分析音频的"atom"或"chunk":
// Set various thresholds based on frame lengths (80, 160 or 240 samples).
if (frame_length == 80) {
overhead1 = self->over_hang_max_1[0];
overhead2 = self->over_hang_max_2[0];
individualTest = self->individual[0];
totalTest = self->total[0];
} else if (frame_length == 160) {
overhead1 = self->over_hang_max_1[1];
overhead2 = self->over_hang_max_2[1];
individualTest = self->individual[1];
totalTest = self->total[1];
} else {
overhead1 = self->over_hang_max_1[2];
overhead2 = self->over_hang_max_2[2];
individualTest = self->individual[2];
totalTest = self->total[2];
}
直觉
因此,音频块(240 个样本)越大,算法越 "aggressive",而较小的 80 个样本帧是 "less aggressive":但这是为什么呢?直觉是什么?
calling-code(使用 vad_core
)为其提供 frames_length
音频块。因此,如果您正在使用 VAD 的音频文件有 10 分钟长,那么在该音频上滑动 window 将生成 frame_length
块并将其传递给此代码。
使用 8000Hz 采样率的音频 运行,当 frame_length
较小 (80) 时,分辨率 (10ms) 是细粒度的,VAD 信号将非常精确。将准确跟踪变化,VAD 估计将为 "reasonable" ... 当 frame_length
较大 (240) 时,分辨率更高 "coarse",并且 VAD 信号将更少调整信号语音的微小(<30 毫秒)变化-activity ... 因此 "less cautious"。
因此,我宁愿谈论 "cautiously" 或 "assertively" 它如何跟踪它正在估计的基础语音信号,而不是咄咄逼人。
我希望这有助于推断它在做什么。至于值本身,它们只是由于不同大小的音频帧而变化的算法细节。