TensorFlow models 中的 VGGish:AudioSet 128 维音频嵌入模型的完整使用指南
2026/9/7 6:06:14 网站建设 项目流程

TensorFlow models 中的 VGGish:AudioSet 128 维音频嵌入模型的完整使用指南

【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models

本文基于 TensorFlow models 仓库research/audioset/vggish目录中的官方实现,系统讲解 VGGish 模型的定义、安装验证、输入特征流水线与输出嵌入后处理的完整链路。读完后,你将能够复现 AudioSet 发布的 128 维音频嵌入:对任意音频做特征提取、加载预训练检查点做推理、按官方格式做 PCA 白化与量化,或在其之上叠加自定义层进行微调训练。

模型定位与代码布局

最初发布的 AudioSet 数据集中包含每个音频片段的 128 维嵌入向量,这些向量由一个在大型 YouTube 数据集上训练的 VGG 风格音频分类模型产生(即后来 YouTube-8M 项目的前身)。仓库提供了该模型的 TensorFlow 定义,称为VGGish,同时附带两部分的支撑代码:把音频波形转换为模型输入特征的前端,以及把模型嵌入输出后处理为与 AudioSet 发布格式一致的模块(见 README)。

VGGish 的两种典型用法:

  • 作为特征提取器:VGGish 把音频输入特征转换为语义化的高层 128 维嵌入,可直接喂给下游分类模型。由于嵌入比原始音频特征语义更紧凑,下游模型通常可以做得更浅。例如,你可以用发布的嵌入训练一个覆盖 AudioSet 中 10 个类别的分类器,之后对任意音频运行本仓库提供的特征提取器与 VGGish 模型,把得到的嵌入喂给该分类器。vggish_inference_demo.py 演示了如何对任意音频产生 VGGish 嵌入。
  • 作为更大模型的一部分:把 VGGish 当作接受音频特征输入的模型的底层"热启动"(warm start),在嵌入层之上再叠加更多层。如果你有与典型 YouTube 视频片段差异较大的大数据集,还可以借此微调 VGGish(或其部分层)。vggish_train_demo.py 演示了如何在 VGGish 之上加层并训练整个模型。

目录内各文件的职责如下(与 README 的 "About the Model" 一节对应):

文件职责
vggish_slim.py模型定义(TensorFlow Slim 表示)
vggish_params.py全部超参数
vggish_input.py音频波形到输入示例的转换器
mel_features.py音频特征提取辅助函数
vggish_postprocess.py嵌入后处理(PCA + 量化)
vggish_inference_demo.py推理模式演示
vggish_train_demo.py训练模式演示
vggish_smoke_test.py安装冒烟测试

安装与依赖验证

VGGish 依赖以下 Python 包(requirements.txt 中已列出,版本要求宽松,较新的版本均可):

  • numpy
  • resampy(重采样)
  • tensorflow
  • tf_slim
  • six
  • soundfile

除依赖包外,还需要下载两个数据文件,并放到与代码相同的目录(下载地址在原 README 中给出):

  • vggish_model.ckpt:TensorFlow checkpoint 格式的 VGGish 预训练模型检查点;
  • vggish_pca_params.npz:NumPy 压缩归档格式的嵌入 PCA 参数。

下面是 README 给出的示例安装与测试会话(虚拟环境部分为可选,用于把依赖与系统隔离,虚拟环境内不要使用sudo):

# 可选:用 virtualenv 隔离环境 # $ virtualenv vggish # Python 2 # 或 # $ python3 -m venv vggish # Python 3 # 激活:$ source vggish/bin/activate # 以 bash 为例 # 退出:$ deactivate # 先升级 pip,并确认安装了 wheel $ sudo python -m pip install --upgrade pip wheel # 安装全部依赖 $ sudo pip install -r requirements.txt # 进入 models 仓库中的 VGGish 目录(本仓库已包含该代码) $ cd models/research/audioset/vggish # 下载两个数据文件到与代码相同的目录(地址见原 README) # vggish_model.ckpt # vggish_pca_params.npz # 安装就绪,运行冒烟测试 $ python vggish_smoke_test.py # 若输出 "Looks Good To Me" 即安装成功

冒烟测试 vggish_smoke_test.py 的验证逻辑值得细看:它生成一段 3 秒、1 kHz、16 kHz 采样率的正弦波,依次执行重采样(验证resampy可用)、特征提取(断言输出形状为[num_secs, 96, 64])、模型前向、嵌入后处理,最后用 10% 的相对容差校验嵌入的均值/标准差(见 vggish_smoke_test.py#L101-L113):

  • 原始嵌入:期望均值约0.000657,标准差约0.343
  • 后处理嵌入(uint8):期望均值约126.0,标准差约89.3

源文件注释标明这些期望值是在 NumPy 1.21.6 / TF 2.8.2 与 NumPy 1.24.3 / TF 2.13.0(Python 3.10,Linux)上实测的,两组配置结果一致——这为运行环境版本给出了可靠的参考基准。

模型架构:VGG 配置 A 的音频变体

架构相关代码见 vggish_slim.py 与 vggish_params.py。VGGish 是 VGG 模型的变体,具体是 11 个权重层的配置 A(Configuration A)。相对标准 VGG-A 做了三处改动:

  1. 输入尺寸改为 96×64 的对数梅尔频谱音频输入;
  2. 去掉最后一组卷积/最大池化层,卷积/池化从五组减为四组;
  3. 末尾不再是 1000 宽的全连接层,而是128 宽的全连接层,作为紧凑的嵌入层。

模型定义到嵌入层为止。注意:嵌入层不含最终的非线性激活,输出的是激活前的值(pre-activation)。在 VGGish 之上叠加层训练时,应先把嵌入送入你选择的非线性再进入后续层。

核心超参数(vggish_params.py#L22-L42):

参数含义
NUM_FRAMES96输入梅尔频谱补丁的帧数
NUM_BANDS/NUM_MEL_BINS64输入梅尔频谱补丁的频率带数
EMBEDDING_SIZE128嵌入层宽度
SAMPLE_RATE16000目标采样率
STFT_WINDOW_LENGTH_SECONDS0.025STFT 窗长(25 ms)
STFT_HOP_LENGTH_SECONDS0.010STFT 帧移(10 ms)
MEL_MIN_HZ/MEL_MAX_HZ125 / 7500梅尔带覆盖的频段
LOG_OFFSET0.01稳定对数的偏移量
EXAMPLE_WINDOW_SECONDS/EXAMPLE_HOP_SECONDS0.96 / 0.96每个示例 0.96 s,零重叠
QUANTIZE_MIN_VAL/QUANTIZE_MAX_VAL-2.0 / +2.0量化裁剪范围
INIT_STDDEV0.01权重初始化标准差
LEARNING_RATE/ADAM_EPSILON1e-4 / 1e-8内部训练用的 Adam 超参数

网络主体结构在 vggish_slim.py#L91-L106:输入按[batch_size, 96, 64]送入(reshape 为 4 维后卷积),经过

conv1(64) → pool1 → conv2(128) → pool2 → conv3(256×2) → pool3 → conv4(512×2) → pool4 → flatten → fc1(4096×2) → fc2(128, 无激活)

其中fc2通过activation_fn=None显式去除了默认 ReLU,输出张量命名为vggish/embedding。默认约定(vggish_slim.py#L64-L79 的 arg_scope 设置):权重初始化为 N(0, 0.01)、偏置为 0、激活为 ReLU、卷积为 3×3 stride 1 SAME 填充、最大池化为 2×2 stride 2 SAME 填充。

关于张量接口,vggish_params.py#L49-L53 定义了:

  • 输入:vggish/input_features:0,float32,形状[batch_size, 96, 64]
  • 输出:vggish/embedding:0
  • 发布特征名:audio_embedding(写 TFRecord 时使用)。

检查点加载函数load_vggish_slim_checkpoint(vggish_slim.py#L109-L136)可以在初始化所有变量之后调用(即 TensorFlow 文档中的 init_fn),它先在一个独立图里以推理模式列出 VGGish 的全部变量名,再用一个专用Saver只恢复名字匹配的 VGGish 变量——因此即使当前图中还有 VGGish 之上新增的层,加载检查点也不会报错,这正是"在 VGGish 上叠加层再训练"能成立的关键机制。

输入流水线:从波形到 96×64 示例

VGGish 训练时使用的音频特征计算流程(README "Input: Audio Features" 一节)为:

  1. 所有音频重采样为 16 kHz 单声道;
  2. 计算短时傅里叶变换幅度谱:窗长 25 ms、帧移 10 ms、周期性 Hann 窗;
  3. 通过梅尔滤波器组映射到 125–7500 Hz 范围的 64 个梅尔带;
  4. 计算稳定对数梅尔谱:log(mel-spectrum + 0.01),偏移量避免对零取对数;
  5. 将特征切成零重叠的 0.96 秒示例:每个示例覆盖 64 个梅尔带 × 96 帧(每帧 10 ms)。

仓库提供的是纯 NumPy 实现,产出的特征与 Google 内部生产代码非常接近。具体实现要点:

  • 分帧mel_features.py#L21-L45:frame()np.lib.stride_tricks.as_strided实现零拷贝分帧,末尾不完整的帧直接丢弃(不做零填充);
  • 周期性 Hann 窗mel_features.py#L48-L68:periodic_hann()实现的是周期为 N 的完整余弦周期,而非np.hanning()那种周期 N-1 的"对称"窗,更适合傅里叶分析;
  • STFT 幅度mel_features.py#L71-L92:stft_magnitude()对加窗帧做np.fft.rfft取模,FFT 长度为不小于窗长的最小 2 的幂(见 mel_features.py#L214);
  • 赫兹→梅尔换算mel_features.py#L96-L111:采用 HTK 公式mel = 1127 * log(1 + hz / 700)
  • 梅尔滤波器组mel_features.py#L114-L189:spectrogram_to_mel_matrix()按梅尔域线性三角带构建权重矩阵,DC 频带系数恒为 0,最终梅尔谱即M = S · A的矩阵乘法;
  • 总入口mel_features.py#L192-L233:log_mel_spectrogram()把以上步骤串起来,返回(num_frames, num_mel_bins)的对数梅尔谱。

在 vggish_input.py 中,waveform_to_examples()(L37-L81)完成最后的装配:多声道输入先在声道维取均值转单声道;采样率不是 16000 时用resampy.resample重采样;随后计算对数梅尔谱,并按1 / STFT_HOP_LENGTH_SECONDS = 100 Hz的特征采样率把 0.96 秒窗、0.96 秒步长(即example_window_length = example_hop_length = 96帧)再次分帧,输出形状[num_examples, 96, 64]的示例数组。

wavfile_to_examples()(L84-L97)是针对 WAV 的便捷封装:通过soundfileint16读入,断言样本类型为 16 位 PCM,再除以 32768 归一到[-1.0, +1.0]后进入waveform_to_examples。若未安装soundfile,读 WAV 会抛出NotImplementedError,但直接在内存中传入 NumPy 波形仍可使用。

输出流水线:PCA 白化与 8-bit 量化

发布的 AudioSet 嵌入在对外发布前经过了后处理:应用 PCA 变换(实际上同时完成了 PCA 与白化),并把每个嵌入元素量化到 8 bit。这样做的目的是与 YouTube-8M 项目保持格式兼容——该项目以同样的 PCA/白化/量化格式发布了数百万 YouTube 视频的视频嵌入与音频嵌入(README "Output: Embeddings" 一节)。

vGGish_postprocess.py 的Postprocessor实现了同样的变换:

  • 构造时从.npz文件加载pca_eigen_vectors(128×128 矩阵)与pca_means(reshape 成 128×1 列向量),并对形状做了断言校验(vggish_postprocess.py#L42-L50);
  • postprocess()[batch_size, 128]的嵌入批处理:先减去均值再左乘 PCA 矩阵(L75-L76);然后裁剪到[-2.0, +2.0],线性映射到[0, 255]并转为uint8(L80-L89)。

README 同时给出一个重要提示:如果你不需要与发布的嵌入或 YouTube-8M 兼容,可以跳过后处理直接使用原始嵌入;此外原 README 还提供了一个 Colab 入口,演示如何下载模型并对自己的声音数据计算嵌入(链接见原文档)。

推理演示:对任意音频生成嵌入

vggish_inference_demo.py 展示了"特征提取 + 模型加载 + 后处理"三个构件在推理场景下的组合方式。命令行参数(L61-L78):

  • --wav_file:WAV 文件路径(16 位 PCM)。不指定时生成一段 5 秒、1 kHz、44.1 kHz 的正弦波合成输入;
  • --checkpoint:模型检查点路径,默认vggish_model.ckpt
  • --pca_params:PCA 参数路径,默认vggish_pca_params.npz
  • --tfrecord_file:可选,把后处理后的嵌入以 AudioSet 同格式的 SequenceExample 写入 TFRecord。

三种典型调用方式(源自文件 docstring):

# 对 WAV 文件推理并打印嵌入(检查点与 PCA 参数从当前目录读取) $ python vggish_inference_demo.py --wav_file /path/to/a/wav/file # 推理并额外写 TFRecord,同时显式指定检查点与 PCA 参数路径 $ python vggish_inference_demo.py --wav_file /path/to/a/wav/file \ --tfrecord_file /path/to/tfrecord/file \ --checkpoint /path/to/model/checkpoint \ --pca_params /path/to/pca/params # 使用内置合成正弦输入,模型文件从当前目录读取 $ python vggish_inference_demo.py

主流程(vggish_inference_demo.py#L98-L147):wavfile_to_examples()产出示例批 →define_vggish_slim(training=False)定义推理模型 →load_vggish_slim_checkpoint()加载检查点 → 按名字取出vggish/input_features:0vggish/embedding:0sess.run得到原始嵌入 →Postprocessor.postprocess()得到量化嵌入 → 若指定了--tfrecord_file,把批内每一行(约对应 1 秒音频,即 96 个 10 ms 帧)的 128 字节量化嵌入按bytes_list逐条写入特征名audio_embeddingSequenceExample。这正是 AudioSet 发布嵌入的存储格式。

训练演示:在 VGGish 之上加层与微调

vggish_train_demo.py 是一个玩具示例:训练一个区分正弦波、常量信号、白噪声三个类别的分类器。合成波形先转成打乱顺序的对数梅尔示例批并附带 one-hot 标签,再送入一个"VGGish 打底 + 顶部若干层"的模型。命令行参数(L60-L73):

  • --num_batches:喂入的批次数量(默认 30);
  • --train_vggish:True 表示训练时允许 VGGish 参数变化(即微调 VGGish);False 表示 VGGish 参数冻结,仅作为固定特征提取器;
  • --checkpoint:检查点路径,默认vggish_model.ckpt

典型调用:

# 训练 100 步,使用默认位置的检查点,允许微调 VGGish $ python vggish_train_demo.py --num_batches 100 # 训练 50 步,冻结 VGGish(只做特征提取),检查点放在其他位置 $ python vggish_train_demo.py --num_batches 50 \ --train_vggish=False \ --checkpoint /path/to/model/checkpoint

顶部模型的搭建细节(vggish_train_demo.py#L131-L171)值得注意:

  • 由于嵌入是激活前的值,先tf.nn.relu(embeddings)再过 100 单元的全连接层,最后接 3 单元 logits 层 + sigmoid(L139-L145);
  • 损失用sigmoid_cross_entropy_with_logits求均值,支持多标签;
  • 优化器为 Adam,学习率与 epsilon 直接取vggish_params.LEARNING_RATE(1e-4)与vggish_params.ADAM_EPSILON(1e-8),即与内部训练 VGGish 相同的超参数;
  • 训练循环前先tf.global_variables_initializer()初始化全图变量(包括顶部新层),再调用load_vggish_slim_checkpoint()只恢复 VGGish 部分——这与define_vggish_slim(training=FLAGS.train_vggish)trainable标志控制的可训练范围配合,实现了"微调"与"冻结"两种模式的一键切换。

小结

VGGish 在 TensorFlow models 仓库中提供了一条完整的音频嵌入生产链路:16 kHz 重采样 → 周期性 Hann 窗 STFT → 64 带梅尔滤波(125–7500 Hz)→ 稳定对数化 → 0.96 秒零重叠分帧(96×64),送入四组卷积 + 两层 4096 全连接 + 128 维嵌入层的 VGG-A 变体;输出可选择直接作为 pre-activation 嵌入使用,或经 PCA 白化与[-2, 2] → [0, 255]的 8-bit 量化后与 AudioSet/YouTube-8M 发布格式对齐。安装后先跑 vggish_smoke_test.py 验证环境,再用 vggish_inference_demo.py 与 vggish_train_demo.py 分别覆盖推理与微调两条路径。需要说明的是:本实现基于 TensorFlow 1.x API(以tensorflow.compat.v1方式运行)并依赖tf_slim,冒烟测试的期望值在 TF 2.8.2 与 2.13.0 上验证一致,选型与升级版本时应以此为准。

【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询