TensorFlow Dataset map处理后数据形状异常多出一维求助
问题根因
多余维度来自tf.numpy_function的参数配置错误:
- 你给
tf.numpy_function传入的第三个参数Tout是列表[tf.float32],这个写法是告诉TensorFlow:传入的Python函数会返回多个输出值,第一个输出的类型是float32,因此tf.numpy_function会返回一个长度为1的元组,元组里才是你处理好的形状为(257,1001,1)的张量。 - 你把这个单元素元组直接作为特征和label配对传入数据集,相当于多嵌套了一层结构,最终取出单条数据时就会多出一个值为1的前置维度,批处理后这个前置维度也会被保留。
- 另外
tf.numpy_function不会自动把Python函数里的张量形状同步到TensorFlow计算图,需要手动显式设置形状,避免后续形状推断出错。
修复方案
只需要修改map阶段的逻辑即可:
- 把
tf.numpy_function的Tout参数从列表[tf.float32]改为单个类型值tf.float32,匹配你单张量输出的函数逻辑 - 给numpy函数返回的张量显式设置固定形状,避免图模式下形状未知的问题
修复后代码
把原来的map部分替换成如下写法即可:
def read_npy_file(data): # 'data' stores the file name of the numpy binary file storing the features of a particular sound file # as a bytes string. # decode() is called on the bytes string to decode it from a bytes string to a regular string # so that it can passed as a parameter into np.load() data = np.load(data.decode()) # Shape of data is now (1, rows, columns) # Needs to be reshaped to (rows, columns, 1): data = np.reshape(data, (257, 1001, 1)) assert data.shape == (257, 1001, 1), f"Shape of spectrogram is {data.shape}; should be (257, 1001, 1)." return data.astype(np.float32) spectrogram_ds = tf.data.Dataset.from_tensor_slices((specgram_files, labels)) # 修改后的map逻辑 def load_example(file, label): spec = tf.numpy_function(read_npy_file, [file], tf.float32) spec.set_shape((257, 1001, 1)) # 显式声明固定形状,避免图模式下形状丢失 return spec, label spectrogram_ds = spectrogram_ds.map( load_example, num_parallel_calls=tf.data.AUTOTUNE) num_files = len(train_df) num_train = int(0.8 * num_files) num_val = int(0.1 * num_files) num_test = int(0.1 * num_files) spectrogram_ds = spectrogram_ds.shuffle(buffer_size=1000) specgram_train_ds = spectrogram_ds.take(num_train) specgram_test_ds = spectrogram_ds.skip(num_train) specgram_val_ds = specgram_test_ds.take(num_val) specgram_test_ds = specgram_test_ds.skip(num_val)
修复后验证:
- 单条数据取出的形状为
(257, 1001, 1),断言可正常通过 - 调用
batch(batch_size=64)后,批次数据形状为(64, 257, 1001, 1),符合预期输入形状。
内容的提问来源于stack exchange,提问作者AlePouroullis
相关产品推荐
相关产品推荐

