You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow中tf.data.Dataset.map标签传参及自定义标签问题

创建音频数据集的常规方法
# 从文件中收集数据
'''
.....部分代码省略........
'''
# 创建映射函数

def get_label(file_path):
  parts = tf.strings.split(
      input=file_path,
      sep=os.path.sep)
  # 注意:此处使用索引而非元组解包,以支持TensorFlow图模式运行
  return parts[-2]

# 映射函数
def get_waveform_and_label(file_path):
  label = get_label(file_path)
  audio_binary = tf.io.read_file(file_path)
  waveform = decode_audio(audio_binary)
  return waveform, label

AUTOTUNE = tf.data.AUTOTUNE

# 创建数据集
files_ds = tf.data.Dataset.from_tensor_slices(train_files)

# 为数据集中每个数据添加标签最常用的方法是使用tf.data.Dataset.map():
waveform_ds = files_ds.map(
    map_func=get_waveform_and_label,
    num_parallel_calls=AUTOTUNE)

for element in waveform_ds:
  print(element)

执行print后,输出的数据集元素示例(随机选取两条):

(<tf.Tensor: shape=(16000,), dtype=float32, numpy=
array([ 9.1552734e-05,  1.5258789e-04,  2.4414062e-04, ...,
-3.3569336e-04, -3.6621094e-04, -2.4414062e-04], dtype=float32)>, <tf.Tensor: shape=(), dtype=string, numpy=b'right'>)
(<tf.Tensor: shape=(16000,), dtype=float32, numpy=
array([ 0.0010376 ,  0.00097656,  0.00094604, ..., -0.00183105,
-0.00158691, -0.00152588], dtype=float32)>, <tf.Tensor: shape=(), dtype=string, numpy=b'no'>)

技术问题

  1. 在调用tf.data.Dataset.map时未向get_waveform_and_label传递参数,该函数是如何确定要处理的标签类型的?
  2. 若想使用自定义的列表、元组或字典形式的标签(而非从文件路径文件夹中获取),例如:
my_labels = ['relaxation', 'grip', 'ungrip']

除了将my_labels作为常量写入映射函数get_waveform_and_label外,还有其他实现方式吗?


尝试代码(非核心)

RaggedTensor类型的timeframes存储的普通张量示例:

tf.Tensor(
[[0.5369535 0.2724565 0.073154  ... 0.0074817 0.2035824 0.0882927]
 [0.5376732 0.2733304 0.0730333 ... 0.0017834 0.1970369 0.0859187]
 [0.5307747 0.2692053 0.0720603 ... 0.0029357 0.1989727 0.0866213]
 ...
 [0.5395046 0.2826822 0.0747677 ... 0.0085316 0.1982029 0.0849934]
 [0.5299433 0.2774992 0.073246  ... 0.0083179 0.1994617 0.085429 ]
 [0.5329857 0.278462  0.0736021 ... 0.0070133 0.2008929 0.0860079]], shape=(117, 128), dtype=float64)

tf.Tensor(
[[0.5278226 0.27012   0.0709168 ... 0.0110207 0.1954106 0.0877619]
 [0.5296971 0.2716435 0.0712691 ... 0.005279  0.1967631 0.0881876]
 [0.5316442 0.2725459 0.0716114 ... 0.0044511 0.1991368 0.089243 ]
 ...
 [0.5419291 0.2776711 0.0726136 ... 0.0114332 0.1941741 0.0884957]
 [0.5319294 0.2723156 0.071426  ... 0.010159  0.1962118 0.0891404]
 [0.5338816 0.2737131 0.0718814 ... 0.0103788 0.1974683 0.0897296]], shape=(118, 128), dtype=float64)

尝试的映射代码:

def maplabel(dataset, tensored_label):
    return dataset, tensored_label

def get_timeFrames_with_label(timeframes:tf.RaggedTensor, \
                              label:str):

    samplesCount = timeframes.shape[0]
    dataset_lines = [None] * samplesCount
    str_tensors = [None] * samplesCount

    
    for i in range(samplesCount):
        dataset_lines[i] = tf.data.Dataset.from_tensors(timeframes[i])
        str_tensors[i] = tf.constant(label, dtype=tf.string)
    
    com1tframes_ds = tf.data.Dataset.choose_from_datasets(dataset_lines, tf.data.Dataset.range(samplesCount))
    # command_ds = tf.data.Dataset.from_tensor_slices(str_tensors) 
    # ...Dataset.zip(com1tframes_ds, command_ds) 报错:"command_ds has no function
    # string.isidentifier"
    
    com1tframes_ds.map(map_func=maplabel(com1tframes_ds, label), \
                       num_parallel_calls=tf.data.AUTOTUNE)

问题解答

问题1:map方法的参数传递逻辑

tf.data.Dataset.map会自动将数据集的每个元素作为参数传入映射函数。在你的代码中,files_ds的每个元素是单个文件路径字符串,所以调用map(get_waveform_and_label)时,每个文件路径会被自动传给get_waveform_and_label的file_path参数。

标签类型由get_label函数决定:它从文件路径中解析出文件夹名(parts[-2]),TensorFlow会自动将其转为string类型的张量,这就是输出中标签为b'right'这类字符串张量的原因。

问题2:自定义标签的灵活实现方式

除了硬编码到映射函数,还有两种更合理的方式:

方式1:用tf.data.Dataset.zip配对数据和标签

如果数据和标签一一对应,可分别创建数据集后用zip合并:

# 假设timeframes是数据张量(或RaggedTensor),my_labels是对应标签列表
data_ds = tf.data.Dataset.from_tensor_slices(timeframes)
labels_ds = tf.data.Dataset.from_tensor_slices(my_labels)
# 配对成(数据,标签)格式的数据集
dataset = tf.data.Dataset.zip((data_ds, labels_ds))

若timeframes是RaggedTensor,from_tensor_slices会自动按第一维度拆分样本,与标签一一匹配。

方式2:用lambda或偏函数传递额外参数

若需给所有样本统一添加某个标签,可通过lambda包装映射函数:

def add_label(data, label):
    return data, label

target_label = 'relaxation'
data_ds = tf.data.Dataset.from_tensor_slices(timeframes)
dataset = data_ds.map(lambda x: add_label(x, target_label), num_parallel_calls=AUTOTUNE)

修复尝试代码的错误

你的代码中map调用有误:map_func需要传入函数对象,而非函数执行结果。同时choose_from_datasets在此场景下冗余,直接用from_tensor_slices更简洁:

def get_timeFrames_with_label(timeframes: tf.RaggedTensor, label: str):
    # 从RaggedTensor创建数据数据集
    data_ds = tf.data.Dataset.from_tensor_slices(timeframes)
    # 创建对应标签的数据集,每个样本对应同一标签
    label_ds = tf.data.Dataset.from_tensors(label).repeat(timeframes.shape[0])
    # 配对数据与标签
    return tf.data.Dataset.zip((data_ds, label_ds))

或用lambda映射实现:

def get_timeFrames_with_label(timeframes: tf.RaggedTensor, label: str):
    data_ds = tf.data.Dataset.from_tensor_slices(timeframes)
    return data_ds.map(lambda x: (x, tf.constant(label, dtype=tf.string)), 
                       num_parallel_calls=tf.data.AUTOTUNE)

内容的提问来源于stack exchange,提问作者Hell576

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:39:52