如何在tf.data的map函数中创建N份标签副本匹配音频帧
tf.data音频切分后标签对齐实现方案
核心实现逻辑
因为tf.signal.frame返回的帧张量第一维为单音频切分后的总帧数N,你只需要先获取N的数值,将单标签重复N次完成长度对齐,再根据训练需求选择是返回对齐后的张量组,还是拆分为逐帧独立样本即可。
场景1:返回帧张量+对齐标签张量
如果你的后续逻辑需要一次性拿到单音频切出的所有帧和对应标签(即输出形状为(N, 单帧采样点数)的波形张量,和形状为(N,)的标签张量),直接补全get_waveform_and_label函数即可:
def get_waveform_and_label(file_path): label = get_label(file_path) waveform = get_waveform(file_path) # 获取切分后的总帧数N n_frames = tf.shape(waveform)[0] # 将标签重复N次,和帧的第一维长度对齐 label = tf.repeat(label, n_frames) return waveform, label
注意:这种写法下,tf.data会把单音频切出的所有帧+对应标签整体当做一个样本输出。
场景2:逐帧拆分为独立训练样本
如果你的训练需要把每段3秒的切分帧当做独立样本(即pipeline迭代时每次输出(单帧波形, 单个标签)),不能直接在map函数中返回对齐后的张量,需要配合数据集切片、打平操作实现:
# 1. 构建音频文件路径数据集 file_ds = tf.data.Dataset.list_files("你的音频文件根目录/*/*.wav") def get_waveform_and_label(file_path): label = get_label(file_path) waveform = get_waveform(file_path) n_frames = tf.shape(waveform)[0] label = tf.repeat(label, n_frames) # 沿第一维将N帧+N个标签切分为N个独立样本 return tf.data.Dataset.from_tensor_slices((waveform, label)) # 2. 映射后打平嵌套数据集,得到逐帧的样本流 waveform_label_ds = file_ds.map( get_waveform_and_label, num_parallel_calls=tf.data.AUTOTUNE ).flat_map(lambda ds: ds)
tf.repeat会自动适配张量类型,字符串格式的标签也可以直接完成重复操作num_parallel_calls=tf.data.AUTOTUNE可以并行处理音频读取、切分逻辑,提升pipeline运行效率flat_map会把单音频生成的包含N个样本的子数据集打平,合并到全局数据集中,不会出现样本嵌套问题
内容的提问来源于stack exchange,提问作者Yeshwant Singh
相关产品推荐
相关产品推荐

