Tensorflow tf.data.Dataset Can I map datasets to return nested list?

Viewed 236

For a given audio file paths, I want them to get the decoded audio in nested list form.
For example,

import tensorflow as tf
import tensorflow.keras as keras
import soundfile as sf

# Soundfile is 8kHz, monophonic
# I want to chop this into 4-second long segments, i.e. [[length of 32000], [length of 32000], ...]
# All files are about 11 ~ 15 seconds, i.e. length of nested list is either 3 or 4.

# Simple version
def do_sf(x, bsize=8000*4):
    readed = sf.read(x.numpy())[0]
    num = len(readed) // bsize
    parts = readed[:(num*bsize)]
    return parts

asdf_ds = tf.data.Dataset.list_files(file_paths)
asdf_ds = asdf_ds.map(lambda x: tf.py_function(do_sf, [x], tf.float64))
next(iter(asdf_ds))
# <tf.Tensor: shape=(96000,), dtype=float64, numpy=
# array([ 0.00961304,  0.00939941, -0.00143433, ...,  0.00723267,
#         0.00592041,  0.00500488])>

So simply reading the file works.

But when I try to map this into [[length of 32000], [length of 32000], [length of 32000]], it doesn't work.

def do_sf2(x, bsize=8000*4):
    readed = sf.read(x.numpy())[0]
    num = len(readed) // bsize
    res = []
    for i in range(num):
        start_idx = bsize * i
        end_idx = bsize * (i+1)
        res.append(readed[start_idx:end_idx])
    return res

asdf_ds = tf.data.Dataset.list_files(file_paths)
asdf_ds = asdf_ds.map(lambda x: tf.py_function(do_sf2, [x], tf.float64))
next(iter(asdf_ds))
# <tf.Tensor: shape=(32000,), dtype=float64, numpy=
# array([0.0098877 , 0.00973511, 0.00360107, ..., 0.02096558, 0.02307129,
#        0.01715088])>

Not the nested list I was expecting.

Maybe Tout argument of tf.py_function() is the problem?

If func returns a list of Tensor and CompositeTensor values: a corresponding list of tf.DTypes and tf.TypeSpecs for each value.

But still not sure how to correct it.

0 Answers
Related