【问题标题】:How to map numpy array in tensorflow dataset如何在张量流数据集中映射numpy数组
【发布时间】:2020-01-12 15:35:14
【问题描述】:

我正在尝试将几个文件加载到我的管道中,每个文件包含 3 个信号,并且 3 个信号以 10 分钟的间隔排序。 当我加载第一个文件时,它具有这种形状(86、75000,3)。 我正在使用张量流 1.14

我尝试了以下代码,为了让您可以使用代码,我用零模拟加载:

import numpy as np
import tensorflow as tf


def my_func(x):
    p = np.zeros([86, 75000, 3])
    return p

def load_sign(path):
    sign = tf.compat.v1.numpy_function(my_func, [path], tf.float64)
    return sign

s = [1, 2]  # list with filenames, these are paths, here i simulate with numbers

AUTOTUNE = tf.data.experimental.AUTOTUNE  
ds = tf.data.Dataset.from_tensor_slices(s)
ds = ds.map(load_sign, num_parallel_calls=AUTOTUNE)

itera = tf.data.make_one_shot_iterator(ds)
x = itera.get_next()

with tf.Session() as sess:
    # sess.run(itera.initializer)
    va_sign = sess.run([x])
    va = np.array(va_sign)
    print(va.shape)

我得到这个形状:(1, 86, 75000, 3) 虽然我想获得 3 个不同的变量,每个变量都具有这种形状:(,75000)

我该怎么做? 我也试过这个代码,但我得到一个错误

import numpy as np
import tensorflow as tf


def my_func(x):
    p = np.zeros([86, 75000, 3])
    x = p[:,:,0]
    y = p[:, :, 1]
    z = p[:, :, 2]
    return x, y, z

# load the signals, in my example it creates the signals using zeros
def load_sign(path):
    a, b, c = tf.compat.v1.numpy_function(my_func, [path], tf.float64)
    return tf.data.Dataset.zip((a,b,c))

s = [1, 2]  # list with filenames, these are paths, here i simulate with numbers

AUTOTUNE = tf.data.experimental.AUTOTUNE  
ds = tf.data.Dataset.from_tensor_slices(s)
ds = ds.map(load_sign, num_parallel_calls=AUTOTUNE)

itera = tf.data.make_one_shot_iterator(ds)
x, y, z = itera.get_next()

with tf.Session() as sess:
    # sess.run(itera.initializer)
    va_sign = sess.run([x])
    va = np.array(va_sign)
    print(va.shape)

在这里,我希望 x 具有这种形状:(86, 75000),但我得到了这个错误。我怎样才能让它工作?更好的是,我可以获得具有这种形状的 x (,75000)

TypeError:张量对象仅在启用急切执行时才可迭代。要迭代此张量,请使用 tf.map_fn。

【问题讨论】:

    标签: python tensorflow tensorflow-datasets


    【解决方案1】:

    numpy_function:
    a, b, c = tf.compat.v1.numpy_function(my_func, [path], tf.float64) 应该返回一个可以在图形环境中使用的 python 函数。变量本身由my_func 返回。所以下面的代码应该是这样的:

    def my_func(x):
        p = np.zeros([86, 75000, 3])
        x = p[:,:,0]
        y = p[:, :, 1]
        z = p[:, :, 2]
        return x, y, z
    
    def load_sign(path):
        func = tf.compat.v1.numpy_function(my_func, [path], [tf.float64, tf.float64, tf.float64])
        return func
    

    其余部分几乎相同,只是稍作调整:

    s = [1, 2]  
    
    AUTOTUNE = tf.data.experimental.AUTOTUNE  
    ds = tf.data.Dataset.from_tensor_slices(s)
    ds = ds.map(load_sign, num_parallel_calls=AUTOTUNE)
    
    itera = tf.data.make_one_shot_iterator(ds)
    output = itera.get_next() # Returns tuple of 3: x,y,z from my_func
    
    with tf.Session() as sess:
        va_sign = sess.run([output])[0] # Unnest single-element list
        for entry in va_sign:
          print(entry.shape)
    

    这将产生 3 个元素,每个元素的形状为 (86, 75000)

    要进一步预处理您的数据并到达(75000,),您可以使用tf.data.Dataset.unbatch()

    AUTOTUNE = tf.data.experimental.AUTOTUNE  
    ds = tf.data.Dataset.from_tensor_slices(s)
    ds = ds.map(load_sign, num_parallel_calls=AUTOTUNE).unbatch()
    
    itera = tf.data.make_one_shot_iterator(ds)
    output = itera.get_next() # Returns tuple of 3: x,y,z from my_func
    

    与上面相同的迭代现在将为您提供三个大小为 (75000) 的元素。

    【讨论】:

    • 非常感谢!我认为 tf 1.14 中不存在 unbatch,但我已经在 colab 上使用 tf 1.15 尝试了您的解决方案,它工作正常,所以我将更新我的 tf 版本。只有一个问题,当我尝试计算数据集中的元素数量时,我希望有 86 个元素,每个元素有 75000 个样本,而我得到 172 个。事实上,当数据集超出范围时,它会像我使用的那样重新启动 repeat(2 )。为什么会发生这种情况?
    • 啊,是的,我在 Colab 上使用 tf 1.15 对其进行了测试,这就是原因。它可能有 172 个元素,因为在示例中您提供了 s = [1, 2]。数据集有两个元素,因此.map 被执行了两次。然后,数据集未批处理,剩下 86*2=172
    • ops 没有注意到我使用了完整的 s,昨天在我的测试中我使用的是 s[0]
    猜你喜欢
    • 2020-03-20
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 2020-12-21
    • 2018-01-17
    相关资源
    最近更新 更多